Files
element-x-ios/UnitTests/Sources/TimelineStateTests.swift
T
Danny eae464ecd7 Timeline: add a Jump to Unread button and a new-message badge on the scroll-to-bottom button. (#5506)
* Timeline: add a Jump to Unread button and a new-message badge on the scroll-to-bottom button.

* Rename scrollToFirstUnread to scrollToReadMarker for consistency with isReadMarkerVisible.

* Cache readMarkerUniqueID and unreadMessageCount as stored properties on TimelineState.

* TimelineViewModel: rename newTimelineItems and drop redundant ordering comment.

* Use Compound chevron icons in TimelineScrollButton.

* Fix TimelineScrollButton layout at large dynamic type sizes.

* Add a trailingAccessory slot to topBanners and use it to dodge banners with the jump-to-read-marker button.

* Put jump-to-read-marker behind a developer-options feature flag.

* Fine-tune TimelineScrollButton sizing and badge colour.

* Remove TimelineScrollButton chevron offset that was compensating for SF Symbol centering.

* Drop the new-messages count, replace with a presence dot.

* Move both timeline scroll buttons to bottom-right and revert topBanners trailingAccessory slot.

* Position TimelineScrollButton badge above for up direction and below for down direction.

* Add long-press mark-as-read pill to the timeline scroll buttons

* Read isSwitchingTimelines from state in updateHasNewMessagesAtBottom.

* Use assertionFailure when scrollToReadMarker is called with no read marker.

* Add TimelineScrollButton preview snapshots.

* (fix) design and various self-review issues

* (fix) suppress scroll button tap after long-press

* (feat) fall back to RoomInfo.fullyReadEventID for jump-to-unread

* (fix) hide jump-to-unread immediately after mark-as-read

* (fix) align with newer matrix-rust-sdk surface

* Bump the RustSDK to v26.05.20

---------

Signed-off-by: Daniel Anderson <daniel.anderson@toptal.com>
Co-authored-by: Stefan Ceriu <stefan.ceriu@gmail.com>
2026-05-21 15:03:32 +03:00

55 lines
2.2 KiB
Swift

//
// Copyright 2026 Element Creations Ltd.
// Copyright 2025 New Vector Ltd.
//
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
// Please see LICENSE files in the repository root for full details.
//
@testable import ElementX
import OrderedCollections
import Testing
struct TimelineStateTests {
// MARK: - Read marker
@Test("Read marker unique ID is captured when present in the timeline")
func readMarkerUniqueIDPresent() {
var state = TimelineState()
state.itemsDictionary[.init("msg1")] = makeTextViewState(uniqueID: "msg1")
state.itemsDictionary[.init("read-marker")] = makeReadMarkerViewState(uniqueID: "read-marker")
state.itemsDictionary[.init("msg2")] = makeTextViewState(uniqueID: "msg2")
state.recomputeReadMarkerUniqueID()
#expect(state.readMarkerUniqueID == .init("read-marker"))
}
@Test("Read marker unique ID is nil when no marker exists")
func readMarkerUniqueIDAbsent() {
var state = TimelineState()
state.itemsDictionary[.init("msg1")] = makeTextViewState(uniqueID: "msg1")
state.itemsDictionary[.init("msg2")] = makeTextViewState(uniqueID: "msg2")
state.recomputeReadMarkerUniqueID()
#expect(state.readMarkerUniqueID == nil)
}
// MARK: - Helpers
private func makeTextViewState(uniqueID: String) -> RoomTimelineItemViewState {
let item = TextRoomTimelineItem(id: .virtual(uniqueID: .init(uniqueID)),
timestamp: .mock,
isOutgoing: false,
isEditable: false,
canBeRepliedTo: true,
sender: .init(id: "@sender:example.com"),
content: .init(body: "Test message"))
return RoomTimelineItemViewState(type: .text(item), groupStyle: .single)
}
private func makeReadMarkerViewState(uniqueID: String) -> RoomTimelineItemViewState {
let item = ReadMarkerRoomTimelineItem(id: .virtual(uniqueID: .init(uniqueID)))
return RoomTimelineItemViewState(type: .readMarker(item), groupStyle: .single)
}
}