import Foundation import Testing @testable import Notes struct AudioNotePayloadTests { @Test func metadataRoundTrips() throws { let payload = AudioNotePayload( id: "01J8Z3M9K7QW2R4T6Y8B0C1D2E", recordedAt: Date(timeIntervalSince1970: 1_700_000_000), duration: 12.5, timeZoneID: "Europe/Berlin" ) let decoded = try #require(AudioNotePayload(metadata: payload.metadata())) #expect(decoded == payload) } @Test func metadataRoundTripsWithoutTimeZone() throws { let payload = AudioNotePayload( id: "01J8Z3M9K7QW2R4T6Y8B0C1D2E", recordedAt: Date(timeIntervalSince1970: 1_700_000_100), duration: 4, timeZoneID: nil ) let dict = payload.metadata() #expect(dict["tz"] == nil) let decoded = try #require(AudioNotePayload(metadata: dict)) #expect(decoded == payload) } /// A survivable trip through actual plist serialization — the metadata really /// crosses WatchConnectivity as a plist dictionary. @Test func metadataSurvivesPlistSerialization() throws { let payload = AudioNotePayload( id: "01J8Z3M9K7QW2R4T6Y8B0C1D2E", recordedAt: Date(timeIntervalSince1970: 1_700_000_050), duration: 7.25, timeZoneID: "America/Los_Angeles" ) let data = try PropertyListSerialization.data( fromPropertyList: payload.metadata(), format: .binary, options: 0) let dict = try #require( try PropertyListSerialization.propertyList(from: data, options: [], format: nil) as? [String: Any]) let decoded = try #require(AudioNotePayload(metadata: dict)) #expect(decoded.id == payload.id) #expect(decoded.duration == payload.duration) #expect(decoded.timeZoneID == payload.timeZoneID) #expect(abs(decoded.recordedAt.timeIntervalSince(payload.recordedAt)) < 0.001) } @Test func decodeRejectsUnknownNewerVersion() { var dict = AudioNotePayload( id: "01J8Z3M9K7QW2R4T6Y8B0C1D2E", recordedAt: Date(), duration: 3, timeZoneID: nil ).metadata() dict["v"] = AudioNotePayload.currentVersion + 1 #expect(AudioNotePayload(metadata: dict) == nil) } @Test func decodeRejectsMissingVersion() { let dict: [String: Any] = [ "id": "01J8Z3M9K7QW2R4T6Y8B0C1D2E", "recordedAt": Date(), "duration": 3.0, ] #expect(AudioNotePayload(metadata: dict) == nil) } @Test func decodeRejectsMissingRequiredField() { // Version present, but no duration. let dict: [String: Any] = [ "v": AudioNotePayload.currentVersion, "id": "01J8Z3M9K7QW2R4T6Y8B0C1D2E", "recordedAt": Date(), ] #expect(AudioNotePayload(metadata: dict) == nil) } @Test func decodeRejectsEmptyMetadata() { #expect(AudioNotePayload(metadata: [:]) == nil) } // MARK: - IngestAck @Test func ackRoundTrips() { let ack = IngestAck(id: "01J8Z3M9K7QW2R4T6Y8B0C1D2E") let decoded = IngestAck(userInfo: ack.userInfo()) #expect(decoded == ack) } @Test func ackRejectsNewerVersionAndForeignUserInfo() { var dict = IngestAck(id: "01J8Z3M9K7QW2R4T6Y8B0C1D2E").userInfo() dict["ackV"] = IngestAck.currentVersion + 1 #expect(IngestAck(userInfo: dict) == nil) #expect(IngestAck(userInfo: [:]) == nil) #expect(IngestAck(userInfo: ["unrelated": true]) == nil) } }