2026-05-15 17:05:13 -07:00
|
|
|
import Foundation
|
|
|
|
|
import Testing
|
|
|
|
|
@testable import IMessageSync
|
|
|
|
|
|
|
|
|
|
@Suite("SyncMessagePayload Serialization")
|
|
|
|
|
struct SyncPayloadTests {
|
|
|
|
|
|
|
|
|
|
private func makePayload(service: String?) -> SyncMessagePayload {
|
|
|
|
|
SyncMessagePayload(
|
|
|
|
|
imessageGuid: "test-guid-001",
|
|
|
|
|
senderId: nil,
|
|
|
|
|
direction: "outgoing",
|
|
|
|
|
sentAt: "2026-03-01T10:00:00Z",
|
|
|
|
|
deliveredAt: nil,
|
|
|
|
|
readAt: nil,
|
|
|
|
|
text: "Hello",
|
|
|
|
|
attributedBody: nil,
|
|
|
|
|
associatedMessageType: nil,
|
|
|
|
|
associatedMessageGuid: nil,
|
|
|
|
|
isAudioMessage: false,
|
|
|
|
|
expressiveSendStyleId: nil,
|
|
|
|
|
replyToGuid: nil,
|
|
|
|
|
threadOriginatorGuid: nil,
|
|
|
|
|
groupTitle: nil,
|
|
|
|
|
balloonBundleId: nil,
|
|
|
|
|
service: service,
|
|
|
|
|
senderIdentifier: nil,
|
|
|
|
|
senderDisplayName: nil,
|
|
|
|
|
senderPhoneNumber: nil,
|
|
|
|
|
senderEmail: nil,
|
|
|
|
|
attachments: [],
|
|
|
|
|
attachmentsCount: 0,
|
|
|
|
|
attachmentsTotalSize: 0,
|
|
|
|
|
attachmentsFiletypes: []
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test func serviceFieldIncludedInDictionary() {
|
|
|
|
|
let dict = makePayload(service: "iMessage").dictionary
|
|
|
|
|
#expect(dict["service"] as? String == "iMessage")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test func smsServiceFieldSerializes() {
|
|
|
|
|
let dict = makePayload(service: "SMS").dictionary
|
|
|
|
|
#expect(dict["service"] as? String == "SMS")
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-15 18:35:50 -07:00
|
|
|
@Test func nilServiceFieldOmittedFromDictionary() {
|
|
|
|
|
// Nil optionals are dropped from the wire payload — the server uses
|
|
|
|
|
// COALESCE semantics so absent ≡ "don't overwrite". Sending explicit
|
|
|
|
|
// nulls would bloat every message payload for no signal.
|
2026-05-15 17:05:13 -07:00
|
|
|
let dict = makePayload(service: nil).dictionary
|
2026-05-15 18:35:50 -07:00
|
|
|
#expect(!dict.keys.contains("service"))
|
2026-05-15 17:05:13 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test func tapbackFieldsSerializeCorrectly() {
|
|
|
|
|
let payload = SyncMessagePayload(
|
|
|
|
|
imessageGuid: "tapback-guid-001",
|
|
|
|
|
senderId: nil,
|
|
|
|
|
direction: "outgoing",
|
|
|
|
|
sentAt: "2026-03-01T10:01:00Z",
|
|
|
|
|
deliveredAt: nil,
|
|
|
|
|
readAt: nil,
|
|
|
|
|
text: nil,
|
|
|
|
|
attributedBody: nil,
|
|
|
|
|
associatedMessageType: 2001,
|
|
|
|
|
associatedMessageGuid: "p:0/parent-guid",
|
|
|
|
|
isAudioMessage: false,
|
|
|
|
|
expressiveSendStyleId: nil,
|
|
|
|
|
replyToGuid: nil,
|
|
|
|
|
threadOriginatorGuid: nil,
|
|
|
|
|
groupTitle: nil,
|
|
|
|
|
balloonBundleId: nil,
|
|
|
|
|
service: "iMessage",
|
|
|
|
|
senderIdentifier: nil,
|
|
|
|
|
senderDisplayName: nil,
|
|
|
|
|
senderPhoneNumber: nil,
|
|
|
|
|
senderEmail: nil,
|
|
|
|
|
attachments: [],
|
|
|
|
|
attachmentsCount: 0,
|
|
|
|
|
attachmentsTotalSize: 0,
|
|
|
|
|
attachmentsFiletypes: []
|
|
|
|
|
)
|
|
|
|
|
let dict = payload.dictionary
|
|
|
|
|
#expect(dict["associatedMessageType"] as? Int == 2001)
|
|
|
|
|
#expect(dict["associatedMessageGuid"] as? String == "p:0/parent-guid")
|
|
|
|
|
#expect(dict["service"] as? String == "iMessage")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Suite("iMessage Struct — Service Field")
|
|
|
|
|
struct iMessageServiceTests {
|
|
|
|
|
|
|
|
|
|
@Test func iMessageStructHoldsServiceField() {
|
|
|
|
|
let msg = iMessage(
|
|
|
|
|
guid: "test-guid",
|
|
|
|
|
conversationId: "conv-001",
|
|
|
|
|
senderId: nil,
|
|
|
|
|
isFromMe: true,
|
|
|
|
|
date: Date(),
|
|
|
|
|
dateDelivered: nil,
|
|
|
|
|
dateRead: nil,
|
|
|
|
|
text: "Hello",
|
|
|
|
|
attributedBody: nil,
|
|
|
|
|
associatedMessageType: nil,
|
|
|
|
|
associatedMessageGuid: nil,
|
|
|
|
|
isAudioMessage: false,
|
|
|
|
|
expressiveSendStyleId: nil,
|
|
|
|
|
replyToGuid: nil,
|
|
|
|
|
threadOriginatorGuid: nil,
|
|
|
|
|
groupTitle: nil,
|
|
|
|
|
balloonBundleId: nil,
|
|
|
|
|
service: "SMS",
|
|
|
|
|
senderIdentifier: nil,
|
|
|
|
|
senderDisplayName: nil,
|
|
|
|
|
senderPhoneNumber: nil,
|
|
|
|
|
senderEmail: nil,
|
|
|
|
|
attachments: [],
|
|
|
|
|
attachmentsCount: 0,
|
|
|
|
|
attachmentsTotalSize: 0,
|
|
|
|
|
attachmentsFiletypes: []
|
|
|
|
|
)
|
|
|
|
|
#expect(msg.service == "SMS")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test func iMessageStructAcceptsNilService() {
|
|
|
|
|
let msg = iMessage(
|
|
|
|
|
guid: "test-guid-nil",
|
|
|
|
|
conversationId: "conv-001",
|
|
|
|
|
senderId: nil,
|
|
|
|
|
isFromMe: false,
|
|
|
|
|
date: Date(),
|
|
|
|
|
dateDelivered: nil,
|
|
|
|
|
dateRead: nil,
|
|
|
|
|
text: "Old message",
|
|
|
|
|
attributedBody: nil,
|
|
|
|
|
associatedMessageType: nil,
|
|
|
|
|
associatedMessageGuid: nil,
|
|
|
|
|
isAudioMessage: false,
|
|
|
|
|
expressiveSendStyleId: nil,
|
|
|
|
|
replyToGuid: nil,
|
|
|
|
|
threadOriginatorGuid: nil,
|
|
|
|
|
groupTitle: nil,
|
|
|
|
|
balloonBundleId: nil,
|
|
|
|
|
service: nil,
|
|
|
|
|
senderIdentifier: nil,
|
|
|
|
|
senderDisplayName: nil,
|
|
|
|
|
senderPhoneNumber: nil,
|
|
|
|
|
senderEmail: nil,
|
|
|
|
|
attachments: [],
|
|
|
|
|
attachmentsCount: 0,
|
|
|
|
|
attachmentsTotalSize: 0,
|
|
|
|
|
attachmentsFiletypes: []
|
|
|
|
|
)
|
|
|
|
|
#expect(msg.service == nil)
|
|
|
|
|
}
|
|
|
|
|
}
|