Files
ghostgram/submodules/Postbox/Tests/MessageViewMediaUpdateTests.swift
ichmagmaus111andClaude Opus 5.5 0622057a4f Ghostgram: open-source release
Ghostgram for iOS, rebuilt from scratch on Telegram iOS 13.0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 17:57:09 +01:00

146 lines
6.6 KiB
Swift

import Foundation
import XCTest
@testable import Postbox
/// The single-message and multi-message views must show a media update the same way
/// the full history view does, whether the media is embedded in the one message that
/// uses it or shared by several messages through a media record of its own.
final class MessageViewMediaUpdateTests: XCTestCase {
private var fixture: PostboxFixture!
private let peer: Int64 = 600
private let sharedMediaId = MediaId(namespace: 0, id: 6001)
private let embeddedMediaId = MediaId(namespace: 0, id: 6002)
private let albumMediaId = MediaId(namespace: 0, id: 6003)
private let albumGroupingKey: Int64 = 77
override func setUp() {
super.setUp()
self.fixture = PostboxFixture(name: "MessageViewMediaUpdateTests")
self.fixture.transaction { transaction in
let _ = transaction.addMessages([
self.message(1, media: FixtureMedia(id: self.sharedMediaId, label: "old")),
self.message(2, media: FixtureMedia(id: self.sharedMediaId, label: "old")),
self.message(3, media: FixtureMedia(id: self.embeddedMediaId, label: "old")),
// An album of two messages whose photos share one media record.
self.message(4, media: FixtureMedia(id: self.albumMediaId, label: "old"), groupingKey: self.albumGroupingKey),
self.message(5, media: FixtureMedia(id: self.albumMediaId, label: "old"), groupingKey: self.albumGroupingKey),
], location: .Random)
}
}
override func tearDown() {
self.fixture.close()
self.fixture = nil
super.tearDown()
}
// MARK: - Helpers
private func messageId(_ id: Int32) -> MessageId {
return MessageHistoryTableFixture.messageId(peer: self.peer, id: id)
}
private func message(_ id: Int32, media: Media, groupingKey: Int64? = nil) -> StoreMessage {
return StoreMessage(id: self.messageId(id), customStableId: nil, globallyUniqueId: nil, groupingKey: groupingKey, threadId: nil, timestamp: 1000 + id, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, authorId: nil, text: "m\(id)", attributes: [], media: [media])
}
private func label(of message: Message?) -> String? {
return (message?.media.first as? FixtureMedia)?.label
}
private func update(_ mediaId: MediaId, to label: String) {
self.fixture.transaction { transaction in
let _ = transaction.updateMedia(mediaId, update: FixtureMedia(id: mediaId, label: label))
}
}
// MARK: - Shared media (a record of its own, no history operation)
func testSingleMessageViewShowsAnUpdateToSharedMedia() {
let recorder = self.fixture.observeMessage(self.messageId(1))
XCTAssertEqual(self.label(of: recorder.waitForValues(count: 1).last?.message), "old")
self.update(self.sharedMediaId, to: "new")
XCTAssertEqual(self.label(of: recorder.waitForValues(count: 2).last?.message), "new")
}
func testMessagesViewShowsAnUpdateToSharedMedia() {
let recorder = self.fixture.observe(.messages([self.messageId(1), self.messageId(2)]), as: MessagesView.self)
XCTAssertEqual(self.label(of: recorder.waitForValues(count: 1).last?.messages[self.messageId(2)]), "old")
self.update(self.sharedMediaId, to: "new")
let view = recorder.waitForValues(count: 2).last
XCTAssertEqual(self.label(of: view?.messages[self.messageId(1)]), "new")
XCTAssertEqual(self.label(of: view?.messages[self.messageId(2)]), "new")
}
/// The view was opened on the local id; the server then confirms the message under
/// a new id, which the view follows through the unchanged stable id.
func testSingleMessageViewFollowsAnIdChangeAndStillShowsMediaUpdates() {
let recorder = self.fixture.observeMessage(self.messageId(1))
recorder.waitForValues(count: 1)
let confirmedId = self.messageId(100)
self.fixture.transaction { transaction in
transaction.updateMessage(self.messageId(1), update: { message in
return .update(MessageHistoryTableFixture.storeMessage(id: confirmedId, timestamp: message.timestamp, text: message.text, media: message.media))
})
}
XCTAssertEqual(recorder.waitForValues(count: 2).last?.message?.id, confirmedId)
self.update(self.sharedMediaId, to: "new")
let view = recorder.waitForValues(count: 3).last
XCTAssertEqual(view?.message?.id, confirmedId, "the view must keep the message it followed, not blank itself")
XCTAssertEqual(self.label(of: view?.message), "new")
}
// MARK: - Embedded media (rewritten inside the message, reported as an operation)
func testSingleMessageViewShowsAnUpdateToEmbeddedMedia() {
let recorder = self.fixture.observeMessage(self.messageId(3))
XCTAssertEqual(self.label(of: recorder.waitForValues(count: 1).last?.message), "old")
self.update(self.embeddedMediaId, to: "new")
XCTAssertEqual(self.label(of: recorder.waitForValues(count: 2).last?.message), "new")
}
func testMessagesViewShowsAnUpdateToEmbeddedMedia() {
let recorder = self.fixture.observe(.messages([self.messageId(3)]), as: MessagesView.self)
XCTAssertEqual(self.label(of: recorder.waitForValues(count: 1).last?.messages[self.messageId(3)]), "old")
self.update(self.embeddedMediaId, to: "new")
XCTAssertEqual(self.label(of: recorder.waitForValues(count: 2).last?.messages[self.messageId(3)]), "new")
}
func testBothViewsShowTheRemovalOfEmbeddedMedia() {
let single = self.fixture.observeMessage(self.messageId(3))
let multiple = self.fixture.observe(.messages([self.messageId(3)]), as: MessagesView.self)
single.waitForValues(count: 1)
multiple.waitForValues(count: 1)
self.fixture.transaction { transaction in
let _ = transaction.updateMedia(self.embeddedMediaId, update: nil)
}
XCTAssertEqual(single.waitForValues(count: 2).last?.message?.media.count, 0)
XCTAssertEqual(multiple.waitForValues(count: 2).last?.messages[self.messageId(3)]?.media.count, 0)
}
// MARK: - Album view
func testMessageGroupViewShowsAnUpdateToSharedMedia() {
let recorder = self.fixture.observe(.messageGroup(id: self.messageId(4)), as: MessageGroupView.self)
XCTAssertEqual(recorder.waitForValues(count: 1).last?.messages.map { self.label(of: $0) }, ["old", "old"])
self.update(self.albumMediaId, to: "new")
XCTAssertEqual(recorder.waitForValues(count: 2).last?.messages.map { self.label(of: $0) }, ["new", "new"])
}
}