Files
Luma/Tests/MessageInteractionTests.swift
2026-07-30 20:07:51 +07:00

121 lines
4.4 KiB
Swift

import Foundation
import XCTest
@testable import Luma
final class MessageInteractionTests: XCTestCase {
func testReplyMetadataRoundTrips() throws {
let message = ChatMessage(
conversationID: "bob@example.org",
senderJID: "alice@example.org",
body: "Ответ",
direction: .outgoing,
delivery: .sent,
security: .omemo,
replyToID: "original-id",
replyToJID: "bob@example.org",
replyPreview: "Исходный текст"
)
let data = try JSONEncoder().encode(message)
let decoded = try JSONDecoder().decode(ChatMessage.self, from: data)
XCTAssertEqual(decoded.replyToID, "original-id")
XCTAssertEqual(decoded.replyToJID, "bob@example.org")
XCTAssertEqual(decoded.replyPreview, "Исходный текст")
}
func testRetractedMessageCannotBeEditedRepliedOrForwarded() {
let message = ChatMessage(
conversationID: "bob@example.org",
senderJID: "alice@example.org",
body: "Удалено",
direction: .outgoing,
delivery: .delivered,
security: .omemo,
retractedAt: Date()
)
XCTAssertFalse(message.canBeEdited)
XCTAssertFalse(message.canBeRepliedTo)
XCTAssertFalse(message.canBeForwarded)
XCTAssertFalse(message.canBeRetracted)
XCTAssertEqual(message.previewText, "🚫 Сообщение удалено")
}
func testLegacyMessageWithoutInteractionFieldsStillDecodes() throws {
let original = ChatMessage(
conversationID: "bob@example.org",
senderJID: "alice@example.org",
body: "Старый архив",
direction: .incoming,
delivery: .delivered,
security: .omemo
)
let encoded = try JSONEncoder().encode(original)
var object = try XCTUnwrap(JSONSerialization.jsonObject(with: encoded) as? [String: Any])
for key in [
"replyToID", "replyToJID", "replyPreview", "forwardedFrom", "retractedAt",
"stanzaID", "senderDisplayName", "isGroupMessage", "callHistory"
] {
object.removeValue(forKey: key)
}
let decoded = try JSONDecoder().decode(
ChatMessage.self,
from: JSONSerialization.data(withJSONObject: object)
)
XCTAssertNil(decoded.replyToID)
XCTAssertNil(decoded.retractedAt)
XCTAssertEqual(decoded.body, "Старый архив")
XCTAssertFalse(decoded.isGroupMessage)
}
func testGroupReplyRequiresRoomAssignedStanzaID() {
var message = ChatMessage(
conversationID: "team@conference.example.org",
senderJID: "team@conference.example.org/alice",
body: "Сообщение группы",
direction: .incoming,
delivery: .delivered,
security: .omemo,
senderDisplayName: "Alice",
isGroupMessage: true
)
XCTAssertFalse(message.canBeRepliedTo)
message.stanzaID = "room-stable-id"
XCTAssertTrue(message.canBeRepliedTo)
XCTAssertEqual(message.replyIdentifier, "room-stable-id")
XCTAssertEqual(message.security, .omemo)
XCTAssertFalse(message.canBeEdited)
XCTAssertFalse(message.canBeRetracted)
}
func testCompletedVideoCallHistoryRoundTripsWithDuration() throws {
let metadata = CallHistoryMetadata(isVideo: true, outcome: .completed)
let message = ChatMessage(
id: "call-alice-123",
conversationID: "alice@example.org",
senderJID: "me@example.org",
body: "Видеозвонок",
direction: .outgoing,
delivery: .sent,
security: .plaintext,
kind: .system,
duration: 65,
callHistory: metadata
)
let data = try JSONEncoder().encode(message)
let decoded = try JSONDecoder().decode(ChatMessage.self, from: data)
XCTAssertEqual(decoded.callHistory, metadata)
XCTAssertEqual(decoded.callTitle, "Исходящий видеозвонок")
XCTAssertEqual(decoded.callSubtitle, "Длительность 1:05")
XCTAssertEqual(decoded.previewText, "🎥 Исходящий видеозвонок")
XCTAssertFalse(decoded.canBeRepliedTo)
XCTAssertFalse(decoded.canBeForwarded)
}
}