Skip to content

Commit 248c42c

Browse files
authored
OCKOutcomeValue requiring all key values (#508)
1 parent 4d18cb0 commit 248c42c

File tree

2 files changed

+101
-25
lines changed

2 files changed

+101
-25
lines changed

CareKitStore/CareKitStore/Structs/OCKOutcomeValue.swift

+29-25
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ public struct OCKOutcomeValue: Codable, Equatable, OCKObjectCompatible, CustomSt
5858
case
5959
kind, units, uuid, value, type, index,
6060
createdDate, updatedDate, schemaVersion, tags,
61-
groupIdentifier, remoteID, userInfo, source, timezone
61+
groupIdentifier, remoteID, userInfo, source, timezone, asset, notes
6262
}
6363

6464
public init(from decoder: Decoder) throws {
@@ -80,29 +80,31 @@ public struct OCKOutcomeValue: Codable, Equatable, OCKObjectCompatible, CustomSt
8080
value = try container.decode(Date.self, forKey: .value)
8181
}
8282

83-
kind = try container.decode(String?.self, forKey: .kind)
84-
units = try container.decode(String?.self, forKey: .units)
85-
index = try container.decode(Int?.self, forKey: .index)
86-
uuid = try container.decode(UUID?.self, forKey: .uuid)
87-
createdDate = try container.decode(Date?.self, forKey: .createdDate)
88-
updatedDate = try container.decode(Date?.self, forKey: .updatedDate)
89-
schemaVersion = try container.decode(OCKSemanticVersion?.self, forKey: .schemaVersion)
90-
groupIdentifier = try container.decode(String?.self, forKey: .groupIdentifier)
91-
tags = try container.decode([String]?.self, forKey: .tags)
92-
remoteID = try container.decode(String?.self, forKey: .remoteID)
93-
source = try container.decode(String?.self, forKey: .source)
94-
userInfo = try container.decode([String: String]?.self, forKey: .userInfo)
83+
kind = try container.decodeIfPresent(String.self, forKey: .kind)
84+
units = try container.decodeIfPresent(String.self, forKey: .units)
85+
index = try container.decodeIfPresent(Int.self, forKey: .index)
86+
uuid = try container.decodeIfPresent(UUID.self, forKey: .uuid)
87+
createdDate = try container.decodeIfPresent(Date.self, forKey: .createdDate)
88+
updatedDate = try container.decodeIfPresent(Date.self, forKey: .updatedDate)
89+
schemaVersion = try container.decodeIfPresent(OCKSemanticVersion.self, forKey: .schemaVersion)
90+
groupIdentifier = try container.decodeIfPresent(String.self, forKey: .groupIdentifier)
91+
tags = try container.decodeIfPresent([String].self, forKey: .tags)
92+
remoteID = try container.decodeIfPresent(String.self, forKey: .remoteID)
93+
source = try container.decodeIfPresent(String.self, forKey: .source)
94+
userInfo = try container.decodeIfPresent([String: String].self, forKey: .userInfo)
9595
timezone = try container.decode(TimeZone.self, forKey: .timezone)
96+
asset = try container.decodeIfPresent(String.self, forKey: .asset)
97+
notes = try container.decodeIfPresent([OCKNote].self, forKey: .notes)
9698
}
9799

98100
public func encode(to encoder: Encoder) throws {
99101
var container = encoder.container(keyedBy: CodingKeys.self)
100102

101103
try container.encode(type, forKey: .type)
102-
try container.encode(kind, forKey: .kind)
103-
try container.encode(units, forKey: .units)
104-
try container.encode(index, forKey: .index)
105-
try container.encode(uuid, forKey: .uuid)
104+
try container.encodeIfPresent(kind, forKey: .kind)
105+
try container.encodeIfPresent(units, forKey: .units)
106+
try container.encodeIfPresent(index, forKey: .index)
107+
try container.encodeIfPresent(uuid, forKey: .uuid)
106108

107109
var encodedValue = false
108110
if let value = integerValue { try container.encode(value, forKey: .value); encodedValue = true } else
@@ -117,14 +119,16 @@ public struct OCKOutcomeValue: Codable, Equatable, OCKObjectCompatible, CustomSt
117119
throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: [CodingKeys.value], debugDescription: message))
118120
}
119121

120-
try container.encode(updatedDate, forKey: .updatedDate)
121-
try container.encode(createdDate, forKey: .createdDate)
122-
try container.encode(schemaVersion, forKey: .schemaVersion)
123-
try container.encode(groupIdentifier, forKey: .groupIdentifier)
124-
try container.encode(tags, forKey: .tags)
125-
try container.encode(remoteID, forKey: .remoteID)
126-
try container.encode(source, forKey: .source)
127-
try container.encode(userInfo, forKey: .userInfo)
122+
try container.encodeIfPresent(updatedDate, forKey: .updatedDate)
123+
try container.encodeIfPresent(createdDate, forKey: .createdDate)
124+
try container.encodeIfPresent(schemaVersion, forKey: .schemaVersion)
125+
try container.encodeIfPresent(groupIdentifier, forKey: .groupIdentifier)
126+
try container.encodeIfPresent(tags, forKey: .tags)
127+
try container.encodeIfPresent(remoteID, forKey: .remoteID)
128+
try container.encodeIfPresent(source, forKey: .source)
129+
try container.encodeIfPresent(userInfo, forKey: .userInfo)
130+
try container.encodeIfPresent(asset, forKey: .asset)
131+
try container.encodeIfPresent(notes, forKey: .notes)
128132
try container.encode(timezone, forKey: .timezone)
129133
}
130134

CareKitStore/CareKitStoreTests/Structs/TestOutcomeValue.swift

+72
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,78 @@ class TestOutcomeValue: XCTestCase {
116116
testEqualityOfEncodings(outcome1: value1, outcome2: value2)
117117
}
118118
}
119+
120+
func testProperDecodingWhenMissingValues() throws {
121+
let valueToDecode = "{\"value\": 10,\"timezone\": {\"identifier\": \"America/New_York\"},\"type\": \"\(OCKOutcomeValueType.integer.rawValue)\"}"
122+
123+
guard let data = valueToDecode.data(using: .utf8) else {
124+
throw OCKStoreError.invalidValue(reason: "Error: Couldn't get data as utf8")
125+
}
126+
127+
let decoded = try JSONDecoder().decode(OCKOutcomeValue.self, from: data)
128+
129+
XCTAssertNil(decoded.asset)
130+
XCTAssertNil(decoded.notes)
131+
XCTAssertEqual(decoded.timezone, TimeZone(identifier: "America/New_York"))
132+
if let decodedUnderValue = decoded.value as? Int {
133+
XCTAssertEqual(decodedUnderValue, 10)
134+
} else {
135+
XCTFail("Should have underlying value")
136+
}
137+
}
138+
139+
func testCodingAllEntries() throws {
140+
var value = OCKOutcomeValue(10)
141+
let valueNote = OCKNote(author: "myId", title: "hello", content: "world")
142+
143+
//Value
144+
value.index = 0
145+
value.kind = "whale"
146+
value.units = "m/s"
147+
148+
//OCKObjectCompatible
149+
value.uuid = UUID()
150+
value.createdDate = Date().addingTimeInterval(-200)
151+
value.updatedDate = Date().addingTimeInterval(-99)
152+
value.timezone = .current
153+
value.userInfo = ["String": "String"]
154+
value.remoteID = "we"
155+
value.groupIdentifier = "mine"
156+
value.tags = ["one", "two"]
157+
value.schemaVersion = .init(majorVersion: 4)
158+
value.source = "yo"
159+
value.asset = "pic"
160+
value.notes = [valueNote]
161+
162+
let encoded = try JSONEncoder().encode(value)
163+
let decoded = try JSONDecoder().decode(OCKOutcomeValue.self, from: encoded)
164+
165+
XCTAssertEqual(decoded.index, value.index)
166+
XCTAssertEqual(decoded.kind, value.kind)
167+
XCTAssertEqual(decoded.units, value.units)
168+
if let decodedUnderValue = decoded.value as? Int,
169+
let currentUnderValue = value.value as? Int {
170+
XCTAssertEqual(decodedUnderValue, currentUnderValue)
171+
} else {
172+
XCTFail("Should have underlying value")
173+
}
174+
175+
XCTAssertEqual(decoded.uuid, value.uuid)
176+
XCTAssertEqual(decoded.createdDate, value.createdDate)
177+
XCTAssertEqual(decoded.updatedDate, value.updatedDate)
178+
XCTAssertEqual(decoded.timezone, value.timezone)
179+
XCTAssertEqual(decoded.userInfo, value.userInfo)
180+
XCTAssertEqual(decoded.remoteID, value.remoteID)
181+
XCTAssertEqual(decoded.source, value.source)
182+
XCTAssertEqual(decoded.schemaVersion, value.schemaVersion)
183+
XCTAssertEqual(decoded.tags, value.tags)
184+
XCTAssertEqual(decoded.groupIdentifier, value.groupIdentifier)
185+
XCTAssertEqual(decoded.asset, value.asset)
186+
XCTAssertEqual(decoded.notes?.count, 1)
187+
XCTAssertEqual(decoded.notes?.first?.author, "myId")
188+
XCTAssertEqual(decoded.notes?.first?.title, "hello")
189+
XCTAssertEqual(decoded.notes?.first?.content, "world")
190+
}
119191

120192
func testEvolvingValue() {
121193
var value = OCKOutcomeValue("abc")

0 commit comments

Comments
 (0)