Skip to content

Commit 18808b4

Browse files
committed
test: expand RFC3339Strategy coverage as BDD suites
Restructure RFC3339StrategyTests into @Suite-grouped behaviors (encoding, decoding, decoding failures) with given/when/then bodies. Add real-world coverage that serializes @DATEvalue<RFC3339Strategy> via JSONEncoder and asserts a "Z" offset (not "+0000"), parameterized decode of every offset form, and a malformed-string case asserting DecodingError.dataCorrupted.
1 parent 5727b7f commit 18808b4

1 file changed

Lines changed: 51 additions & 5 deletions

File tree

Tests/KarrotCodableKitTests/BetterCodable/DateValue/RFC3339StrategyTests.swift

Lines changed: 51 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,44 +10,90 @@ import Testing
1010

1111
import KarrotCodableKit
1212

13+
@Suite("RFC3339Strategy")
1314
struct RFC3339StrategyTests {
1415

16+
private struct Fixture: Codable {
17+
@DateValue<RFC3339Strategy> var date: Date
18+
}
19+
}
20+
21+
// MARK: - Encoding a Date
22+
23+
extension RFC3339StrategyTests {
24+
1525
@Test
16-
func encodesUTCDateWithStandardCompliantOffset() {
26+
func encodesUTCDateWithZOffsetInsteadOfRFC822Offset() {
1727
// given
1828
let date = Date(timeIntervalSince1970: 1715082540) // 2024-05-07T11:49:00 UTC
1929

2030
// when
2131
let result = RFC3339Strategy.encode(date)
2232

2333
// then
24-
// RFC 3339 requires the UTC offset to be "Z" (or "+00:00"), not the colon-less "+0000".
34+
// RFC 3339 allows only "Z" or "+00:00" for UTC, never the colon-less "+0000".
2535
#expect(result == "2024-05-07T11:49:00Z")
2636
}
2737

38+
@Test
39+
func serializesUTCDateWithZOffsetViaJSONEncoder() throws {
40+
// given
41+
let date = Date(timeIntervalSince1970: 1715082540) // 2024-05-07T11:49:00 UTC
42+
let fixture = Fixture(date: date)
43+
44+
// when
45+
let data = try JSONEncoder().encode(fixture)
46+
let json = try #require(String(bytes: data, encoding: .utf8))
47+
48+
// then
49+
#expect(json.contains("\"2024-05-07T11:49:00Z\""))
50+
#expect(!json.contains("+0000"))
51+
}
52+
}
53+
54+
// MARK: - Decoding an RFC 3339 string
55+
56+
extension RFC3339StrategyTests {
57+
2858
@Test(arguments: [
2959
"2024-05-07T11:49:00Z",
3060
"2024-05-07T11:49:00+00:00",
3161
"2024-05-07T11:49:00+0000"
3262
])
33-
func decodesAllUTCOffsetForms(input: String) throws {
63+
func decodesEveryUTCOffsetFormToSameInstant(input: String) throws {
3464
// when
3565
let date = try RFC3339Strategy.decode(input)
3666

3767
// then
38-
// "ZZZZZ" still parses every offset form the old "Z" pattern accepted, including "+0000".
68+
// "ZZZZZ" still parses every offset form the old "Z" pattern accepted.
3969
#expect(date == Date(timeIntervalSince1970: 1715082540))
4070
}
4171

4272
@Test(arguments: [
4373
"1996-12-19T16:39:57-08:00",
4474
"1996-12-19T16:39:57-0800"
4575
])
46-
func decodesNonUTCOffsetsRegardlessOfColon(input: String) throws {
76+
func decodesNonUTCOffsetsWithOrWithoutColon(input: String) throws {
4777
// when
4878
let date = try RFC3339Strategy.decode(input)
4979

5080
// then
5181
#expect(date == Date(timeIntervalSince1970: 851042397))
5282
}
5383
}
84+
85+
// MARK: - Decoding a malformed string
86+
87+
extension RFC3339StrategyTests {
88+
89+
@Test
90+
func throwsDataCorruptedErrorForMalformedString() {
91+
// when / then
92+
#expect {
93+
try RFC3339Strategy.decode("not-a-valid-date")
94+
} throws: { error in
95+
guard case DecodingError.dataCorrupted = error else { return false }
96+
return true
97+
}
98+
}
99+
}

0 commit comments

Comments
 (0)