diff --git a/Sources/Models/Amiibo.swift b/Sources/Models/Amiibo.swift index 7199c01..4a7ef2b 100644 --- a/Sources/Models/Amiibo.swift +++ b/Sources/Models/Amiibo.swift @@ -4,15 +4,72 @@ public struct Amiibo { public let tail: String public let name: String public let character: String - public let amiiboSeries: String + public let series: String public let gameSeries: String public let image: String public let release: Release - public let games3DS: [Game]? - public let gamesWiiU: [Game]? - public let gamesSwitch: [Game]? + public let games: Games? +} + +// MARK: - Structs + +extension Amiibo { + public struct Games: Decodable { + public let n3ds: [Game] + public let wiiu: [Game] + public let `switch`: [Game] + } } // MARK: - Decodable -extension Amiibo: Decodable {} +extension Amiibo: Decodable { + + // MARK: Enumerations + + enum CodingKeys: String, CodingKey { + case type + case head + case tail + case name + case character + case series = "amiiboSeries" + case gameSeries + case image + case release + case games3DS + case gamesWiiU + case gamesSwitch + } + + // MARK: Initialisers + + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + let games3ds = try container.decodeIfPresent([Game].self, forKey: .games3DS) + let gamesWiiU = try container.decodeIfPresent([Game].self, forKey: .gamesWiiU) + let gamesSwitch = try container.decodeIfPresent([Game].self, forKey: .gamesSwitch) + + self.type = try container.decode(String.self, forKey: .type) + self.head = try container.decode(String.self, forKey: .head) + self.tail = try container.decode(String.self, forKey: .tail) + self.name = try container.decode(String.self, forKey: .name) + self.character = try container.decode(String.self, forKey: .character) + self.series = try container.decode(String.self, forKey: .series) + self.gameSeries = try container.decode(String.self, forKey: .gameSeries) + self.image = try container.decode(String.self, forKey: .image) + self.release = try container.decode(Release.self, forKey: .release) + self.games = { + if let games3ds, let gamesWiiU, let gamesSwitch { + return .init( + n3ds: games3ds, + wiiu: gamesWiiU, + switch: gamesSwitch + ) + } else { + return nil + } + }() + } + +} diff --git a/Tests/Services/AmiiboServiceTests.swift b/Tests/Services/AmiiboServiceTests.swift index e0726ad..af7ef82 100644 --- a/Tests/Services/AmiiboServiceTests.swift +++ b/Tests/Services/AmiiboServiceTests.swift @@ -47,12 +47,8 @@ final class AmiiboServiceTests: XCTestCase { // THEN XCTAssertFalse(result.isEmpty) XCTAssertEqual(result.count, 2) - XCTAssertNil(result.first?.games3DS) - XCTAssertNil(result.first?.gamesWiiU) - XCTAssertNil(result.first?.gamesSwitch) - XCTAssertNil(result.last?.games3DS) - XCTAssertNil(result.last?.gamesWiiU) - XCTAssertNil(result.last?.gamesSwitch) + XCTAssertNil(result.first?.games) + XCTAssertNil(result.last?.games) } func test_amiibos_withGameData() async throws { @@ -71,24 +67,24 @@ final class AmiiboServiceTests: XCTestCase { // THEN XCTAssertFalse(result.isEmpty) XCTAssertEqual(result.count, 2) - XCTAssertNotNil(result.first?.games3DS) - XCTAssertEqual(result.first?.games3DS?.count, 21) - XCTAssertNil(result.first?.games3DS?.first?.usage) - XCTAssertNotNil(result.first?.gamesWiiU) - XCTAssertEqual(result.first?.gamesWiiU?.count, 8) - XCTAssertNil(result.first?.gamesWiiU?.first?.usage) - XCTAssertNotNil(result.first?.gamesSwitch) - XCTAssertEqual(result.first?.gamesSwitch?.count, 8) - XCTAssertNil(result.first?.gamesSwitch?.first?.usage) - XCTAssertNotNil(result.last?.games3DS) - XCTAssertEqual(result.last?.games3DS?.count, 22) - XCTAssertNil(result.last?.games3DS?.first?.usage) - XCTAssertNotNil(result.last?.gamesWiiU) - XCTAssertEqual(result.last?.gamesWiiU?.count, 8) - XCTAssertNil(result.last?.gamesWiiU?.first?.usage) - XCTAssertNotNil(result.last?.gamesSwitch) - XCTAssertEqual(result.last?.gamesSwitch?.count, 9) - XCTAssertNil(result.last?.gamesSwitch?.first?.usage) + XCTAssertNotNil(result.first?.games) + XCTAssertEqual(result.first?.games?.n3ds.count, 21) + XCTAssertNil(result.first?.games?.n3ds.first?.usage) + XCTAssertNotNil(result.first?.games?.wiiu) + XCTAssertEqual(result.first?.games?.wiiu.count, 8) + XCTAssertNil(result.first?.games?.wiiu.first?.usage) + XCTAssertNotNil(result.first?.games?.switch) + XCTAssertEqual(result.first?.games?.switch.count, 8) + XCTAssertNil(result.first?.games?.switch.first?.usage) + XCTAssertNotNil(result.last?.games?.n3ds) + XCTAssertEqual(result.last?.games?.n3ds.count, 22) + XCTAssertNil(result.last?.games?.n3ds.first?.usage) + XCTAssertNotNil(result.last?.games?.wiiu) + XCTAssertEqual(result.last?.games?.wiiu.count, 8) + XCTAssertNil(result.last?.games?.wiiu.first?.usage) + XCTAssertNotNil(result.last?.games?.switch) + XCTAssertEqual(result.last?.games?.switch.count, 9) + XCTAssertNil(result.last?.games?.switch.first?.usage) } func test_amiibos_withUsageData() async throws { @@ -107,30 +103,30 @@ final class AmiiboServiceTests: XCTestCase { // THEN XCTAssertFalse(result.isEmpty) XCTAssertEqual(result.count, 2) - XCTAssertNotNil(result.first?.games3DS) - XCTAssertEqual(result.first?.games3DS?.count, 21) - XCTAssertNotNil(result.first?.games3DS?.first?.usage) - XCTAssertEqual(result.first?.games3DS?.first?.usage?.count, 1) - XCTAssertNotNil(result.first?.gamesWiiU) - XCTAssertEqual(result.first?.gamesWiiU?.count, 8) - XCTAssertNotNil(result.first?.gamesWiiU?.first?.usage) - XCTAssertEqual(result.first?.gamesWiiU?.first?.usage?.count, 1) - XCTAssertNotNil(result.first?.gamesSwitch) - XCTAssertEqual(result.first?.gamesSwitch?.count, 8) - XCTAssertNotNil(result.first?.gamesSwitch?.first?.usage) - XCTAssertEqual(result.first?.gamesSwitch?.first?.usage?.count, 1) - XCTAssertNotNil(result.last?.games3DS) - XCTAssertEqual(result.last?.games3DS?.count, 22) - XCTAssertNotNil(result.last?.games3DS?.first?.usage) - XCTAssertEqual(result.last?.games3DS?.first?.usage?.count, 1) - XCTAssertNotNil(result.last?.gamesWiiU) - XCTAssertEqual(result.last?.gamesWiiU?.count, 8) - XCTAssertNotNil(result.last?.gamesWiiU?.first?.usage) - XCTAssertEqual(result.last?.gamesWiiU?.first?.usage?.count, 1) - XCTAssertNotNil(result.last?.gamesSwitch) - XCTAssertEqual(result.last?.gamesSwitch?.count, 9) - XCTAssertNotNil(result.last?.gamesSwitch?.first?.usage) - XCTAssertEqual(result.last?.gamesSwitch?.first?.usage?.count, 1) + XCTAssertNotNil(result.first?.games?.n3ds) + XCTAssertEqual(result.first?.games?.n3ds.count, 21) + XCTAssertNotNil(result.first?.games?.n3ds.first?.usage) + XCTAssertEqual(result.first?.games?.n3ds.first?.usage?.count, 1) + XCTAssertNotNil(result.first?.games?.wiiu) + XCTAssertEqual(result.first?.games?.wiiu.count, 8) + XCTAssertNotNil(result.first?.games?.wiiu.first?.usage) + XCTAssertEqual(result.first?.games?.wiiu.first?.usage?.count, 1) + XCTAssertNotNil(result.first?.games?.switch) + XCTAssertEqual(result.first?.games?.switch.count, 8) + XCTAssertNotNil(result.first?.games?.switch.first?.usage) + XCTAssertEqual(result.first?.games?.switch.first?.usage?.count, 1) + XCTAssertNotNil(result.last?.games?.n3ds) + XCTAssertEqual(result.last?.games?.n3ds.count, 22) + XCTAssertNotNil(result.last?.games?.n3ds.first?.usage) + XCTAssertEqual(result.last?.games?.n3ds.first?.usage?.count, 1) + XCTAssertNotNil(result.last?.games?.wiiu) + XCTAssertEqual(result.last?.games?.wiiu.count, 8) + XCTAssertNotNil(result.last?.games?.wiiu.first?.usage) + XCTAssertEqual(result.last?.games?.wiiu.first?.usage?.count, 1) + XCTAssertNotNil(result.last?.games?.switch) + XCTAssertEqual(result.last?.games?.switch.count, 9) + XCTAssertNotNil(result.last?.games?.switch.first?.usage) + XCTAssertEqual(result.last?.games?.switch.first?.usage?.count, 1) } func test_amiibos_whenDateDecodingStrategyMismatch() async throws {