import Foundation import Testing @testable import ForgejoKit struct DateDecodingTests { private func decoder() -> JSONDecoder { let d = JSONDecoder() d.dateDecodingStrategy = forgejoDateDecodingStrategy return d } private struct DateWrapper: Codable { let date: Date } private var utcCalendar: Calendar { var calendar = Calendar(identifier: .gregorian) calendar.timeZone = TimeZone(identifier: "UTC")! return calendar } // MARK: - ISO 8601 without fractional seconds @Test func decodesDateWithoutFractionalSeconds() throws { let json = #"{"date":"2024-01-15T10:30:00Z"}"# let result = try decoder().decode(DateWrapper.self, from: Data(json.utf8)) #expect(utcCalendar.component(.year, from: result.date) == 2024) #expect(utcCalendar.component(.month, from: result.date) == 1) #expect(utcCalendar.component(.day, from: result.date) == 15) #expect(utcCalendar.component(.hour, from: result.date) == 10) #expect(utcCalendar.component(.minute, from: result.date) == 30) } // MARK: - ISO 8601 with fractional seconds @Test func decodesDateWithFractionalSeconds() throws { let json = #"{"date":"2024-06-20T14:05:30.123Z"}"# let result = try decoder().decode(DateWrapper.self, from: Data(json.utf8)) #expect(utcCalendar.component(.year, from: result.date) == 2024) #expect(utcCalendar.component(.month, from: result.date) == 6) #expect(utcCalendar.component(.day, from: result.date) == 20) #expect(utcCalendar.component(.hour, from: result.date) == 14) } @Test func decodesDateWithTripleZeroFraction() throws { let json = #"{"date":"2024-01-15T10:30:00.000Z"}"# let result = try decoder().decode(DateWrapper.self, from: Data(json.utf8)) #expect(utcCalendar.component(.second, from: result.date) == 0) } // MARK: - Invalid dates @Test func throwsOnInvalidDateString() { let json = #"{"date":"not-a-date"}"# #expect(throws: DecodingError.self) { _ = try decoder().decode(DateWrapper.self, from: Data(json.utf8)) } } @Test func throwsOnEmptyDateString() { let json = #"{"date":""}"# #expect(throws: DecodingError.self) { _ = try decoder().decode(DateWrapper.self, from: Data(json.utf8)) } } // MARK: - Both formats decode to same value @Test func bothFormatsProduceSameDate() throws { let jsonWithout = #"{"date":"2024-03-10T08:00:00Z"}"# let jsonWith = #"{"date":"2024-03-10T08:00:00.000Z"}"# let d = decoder() let resultWithout = try d.decode(DateWrapper.self, from: Data(jsonWithout.utf8)) let resultWith = try d.decode(DateWrapper.self, from: Data(jsonWith.utf8)) #expect(resultWithout.date == resultWith.date) } }