mirror of
https://github.com/ichmagmaus111/ghostgram.git
synced 2026-11-02 22:04:28 +01:00
Ghostgram for iOS, rebuilt from scratch on Telegram iOS 13.0. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
154 lines
6.7 KiB
Swift
154 lines
6.7 KiB
Swift
import XCTest
|
|
import Postbox
|
|
@testable import TelegramCore
|
|
|
|
/// One peer's shared-media list: the server skeleton, and the layout joining it with the local
|
|
/// newest messages (the top section).
|
|
final class SparseMessageListLayoutTests: XCTestCase {
|
|
private let channelId = SparseFixtures.channelId
|
|
private let groupId = SparseFixtures.groupId
|
|
|
|
/// The channel's messages `ids`, newest first, as the local top section holds them.
|
|
private func channelMessages(_ ids: ClosedRange<Int32>) -> [Message] {
|
|
return ids.reversed().map { SparseFixtures.message(self.channelId, $0, timestamp: 1_000_000 + $0) }
|
|
}
|
|
|
|
func testSkeletonKeepsTheLeadingRangeWhenAsked() {
|
|
// Positions arrive in any order; the skeleton is newest first.
|
|
let skeleton = sparseMessageSkeleton(
|
|
peerId: self.groupId,
|
|
positions: [
|
|
SparseMessagePosition(id: 50, date: 500, offset: 20),
|
|
SparseMessagePosition(id: 90, date: 900, offset: 5)
|
|
],
|
|
totalCount: 30,
|
|
includeLeadingRange: true
|
|
)
|
|
XCTAssertEqual(skeleton.items, [
|
|
.range(count: 5),
|
|
.anchor(id: SparseFixtures.messageId(self.groupId, 90), timestamp: 900, message: nil),
|
|
.range(count: 14),
|
|
.anchor(id: SparseFixtures.messageId(self.groupId, 50), timestamp: 500, message: nil),
|
|
.range(count: 9)
|
|
])
|
|
}
|
|
|
|
func testSkeletonLeavesTheLeadingRangeToTheTopSection() {
|
|
let skeleton = sparseMessageSkeleton(
|
|
peerId: self.groupId,
|
|
positions: [
|
|
SparseMessagePosition(id: 90, date: 900, offset: 5),
|
|
SparseMessagePosition(id: 50, date: 500, offset: 20)
|
|
],
|
|
totalCount: 30,
|
|
includeLeadingRange: false
|
|
)
|
|
XCTAssertEqual(skeleton.items, [
|
|
.anchor(id: SparseFixtures.messageId(self.groupId, 90), timestamp: 900, message: nil),
|
|
.range(count: 14),
|
|
.anchor(id: SparseFixtures.messageId(self.groupId, 50), timestamp: 500, message: nil),
|
|
.range(count: 9)
|
|
])
|
|
}
|
|
|
|
func testSkeletonWithoutPositionsIsEmpty() {
|
|
let skeleton = sparseMessageSkeleton(peerId: self.groupId, positions: [], totalCount: 0, includeLeadingRange: true)
|
|
XCTAssertEqual(skeleton.items, [])
|
|
}
|
|
|
|
func testRangeStraddlingTheTopSectionCountsOnlyItsOverflow() {
|
|
// 180 local messages; the server knows positions 0, 150 and 300 of 301.
|
|
let top = self.channelMessages(821 ... 1000)
|
|
let skeleton = sparseMessageSkeleton(
|
|
peerId: self.channelId,
|
|
positions: [
|
|
SparseMessagePosition(id: 1000, date: 0, offset: 0),
|
|
SparseMessagePosition(id: 850, date: 0, offset: 150),
|
|
SparseMessagePosition(id: 700, date: 0, offset: 300)
|
|
],
|
|
totalCount: 301,
|
|
includeLeadingRange: false
|
|
)
|
|
|
|
let layout = sparseMessageListSegmentItems(peerId: self.channelId, topMessages: top, skeleton: skeleton)
|
|
|
|
// The run 151...299 straddles the top section's end. Before the fix it added all 149
|
|
// messages instead of the 120 past the top section, putting position 300 at index 329.
|
|
XCTAssertEqual(layout.totalCount, 301)
|
|
XCTAssertEqual(layout.items.count, 181)
|
|
XCTAssertEqual(SparseFixtures.cells(Array(layout.items.suffix(1))), [
|
|
.placeholder(index: 300, id: SparseFixtures.messageId(self.channelId, 700))
|
|
])
|
|
}
|
|
|
|
func testRangesInsideTheTopSectionAddNothing() {
|
|
// 100 local messages; the server knows positions 0, 40 and 100 of 150.
|
|
let top = self.channelMessages(901 ... 1000)
|
|
let skeleton = sparseMessageSkeleton(
|
|
peerId: self.channelId,
|
|
positions: [
|
|
SparseMessagePosition(id: 1000, date: 0, offset: 0),
|
|
SparseMessagePosition(id: 960, date: 0, offset: 40),
|
|
SparseMessagePosition(id: 900, date: 0, offset: 100)
|
|
],
|
|
totalCount: 150,
|
|
includeLeadingRange: false
|
|
)
|
|
|
|
let layout = sparseMessageListSegmentItems(peerId: self.channelId, topMessages: top, skeleton: skeleton)
|
|
|
|
XCTAssertEqual(layout.totalCount, 150)
|
|
XCTAssertEqual(layout.items.count, 101)
|
|
XCTAssertEqual(SparseFixtures.cells(Array(layout.items.prefix(1))), [
|
|
.message(index: 0, id: SparseFixtures.messageId(self.channelId, 1000), isLocal: true)
|
|
])
|
|
XCTAssertEqual(SparseFixtures.cells(Array(layout.items.suffix(1))), [
|
|
.placeholder(index: 100, id: SparseFixtures.messageId(self.channelId, 900))
|
|
])
|
|
}
|
|
|
|
func testLoadedAnchorsAreRemoteMessages() {
|
|
let loaded = SparseFixtures.message(self.groupId, 90, timestamp: 900)
|
|
let skeleton = SparseMessageSkeleton(items: [
|
|
.anchor(id: loaded.id, timestamp: 900, message: loaded),
|
|
.range(count: 3),
|
|
.anchor(id: SparseFixtures.messageId(self.groupId, 50), timestamp: 500, message: nil)
|
|
])
|
|
|
|
let layout = sparseMessageListSegmentItems(peerId: self.groupId, topMessages: [], skeleton: skeleton)
|
|
|
|
XCTAssertEqual(layout.totalCount, 5)
|
|
XCTAssertEqual(SparseFixtures.cells(layout.items), [
|
|
.message(index: 0, id: loaded.id, isLocal: false),
|
|
.placeholder(index: 4, id: SparseFixtures.messageId(self.groupId, 50))
|
|
])
|
|
}
|
|
|
|
func testTopSectionIgnoresTheMigratedGroupsMessages() {
|
|
// Postbox turns the channel's history view into its `.associated` merge with the group
|
|
// on the next cached-data write, so the top section can end with group messages.
|
|
let top = self.channelMessages(8 ... 10) + [
|
|
SparseFixtures.message(self.groupId, 70, timestamp: 70),
|
|
SparseFixtures.message(self.groupId, 60, timestamp: 60)
|
|
]
|
|
let skeleton = sparseMessageSkeleton(
|
|
peerId: self.channelId,
|
|
positions: [
|
|
SparseMessagePosition(id: 10, date: 0, offset: 0),
|
|
SparseMessagePosition(id: 8, date: 0, offset: 2)
|
|
],
|
|
totalCount: 3,
|
|
includeLeadingRange: false
|
|
)
|
|
|
|
let layout = sparseMessageListSegmentItems(peerId: self.channelId, topMessages: top, skeleton: skeleton)
|
|
|
|
XCTAssertEqual(layout.totalCount, 3)
|
|
XCTAssertEqual(SparseFixtures.cells(layout.items), [
|
|
.message(index: 0, id: SparseFixtures.messageId(self.channelId, 10), isLocal: true),
|
|
.message(index: 1, id: SparseFixtures.messageId(self.channelId, 9), isLocal: true),
|
|
.message(index: 2, id: SparseFixtures.messageId(self.channelId, 8), isLocal: true)
|
|
])
|
|
}
|
|
}
|