Files
Luma/Tests/MessageReplySwipeTests.swift
T
wt cf2bda9c54
iOS CI / Build and Test SwiftUI App (push) Canceled after 0s
Build Unsigned iOS and macOS Apps / Build Unsigned iOS IPA (push) Canceled after 0s
Build Unsigned iOS and macOS Apps / Build macOS ZIP (push) Canceled after 0s
updated up
2026-09-06 01:23:27 +07:00

175 lines
6.5 KiB
Swift

import CoreGraphics
import XCTest
@testable import Luma
final class MessageReplySwipeTests: XCTestCase {
func testRightToLeftSwipeReplies() {
XCTAssertTrue(MessageReplySwipePolicy.shouldReply(
locked: false,
translation: CGSize(width: -70, height: 8),
predictedEndTranslation: CGSize(width: -72, height: 9)
))
XCTAssertLessThan(
MessageReplySwipePolicy.offset(locked: false, translation: CGSize(width: -70, height: 8)),
0
)
}
func testLeftToRightSwipeReplies() {
XCTAssertTrue(MessageReplySwipePolicy.canLock(CGSize(width: 24, height: 10)))
XCTAssertGreaterThan(
MessageReplySwipePolicy.offset(locked: false, translation: CGSize(width: 70, height: 8)),
0
)
XCTAssertGreaterThan(
MessageReplySwipePolicy.offset(locked: true, translation: CGSize(width: 70, height: 8)),
0
)
XCTAssertTrue(MessageReplySwipePolicy.shouldReply(
locked: false,
translation: CGSize(width: 70, height: 8),
predictedEndTranslation: CGSize(width: 72, height: 9)
))
}
func testVerticalTimelineScrollDoesNotReply() {
XCTAssertFalse(MessageReplySwipePolicy.shouldReply(
locked: false,
translation: CGSize(width: -42, height: 80),
predictedEndTranslation: CGSize(width: -50, height: 105)
))
}
func testDiagonalTimelineScrollDoesNotReply() {
XCTAssertFalse(MessageReplySwipePolicy.shouldReply(
locked: false,
translation: CGSize(width: -54, height: 44),
predictedEndTranslation: CGSize(width: -76, height: 58)
))
XCTAssertEqual(
MessageReplySwipePolicy.offset(locked: false, translation: CGSize(width: -54, height: 44)),
0
)
}
func testDiagonalScrollAtOldThresholdDoesNotReply() {
// width/height ≈ 1.5 passed the old 1.4 dominance and moved bubbles
// during scrolling; the stricter policy must stay silent.
XCTAssertFalse(MessageReplySwipePolicy.shouldReply(
locked: false,
translation: CGSize(width: -60, height: 40),
predictedEndTranslation: CGSize(width: -60, height: 40)
))
XCTAssertEqual(
MessageReplySwipePolicy.offset(locked: false, translation: CGSize(width: -60, height: 40)),
0
)
}
func testShortSwipeDoesNotReply() {
XCTAssertFalse(MessageReplySwipePolicy.shouldReply(
locked: false,
translation: CGSize(width: -36, height: 4),
predictedEndTranslation: CGSize(width: -48, height: 5)
))
}
func testFastHorizontalFlickUsesPredictedEnd() {
XCTAssertTrue(MessageReplySwipePolicy.shouldReply(
locked: false,
translation: CGSize(width: -35, height: 3),
predictedEndTranslation: CGSize(width: -90, height: 7)
))
}
func testIndicatorStaysHiddenUntilActivationDistance() {
XCTAssertEqual(
MessageReplySwipePolicy.offset(locked: false, translation: CGSize(width: -20, height: 0)),
0
)
XCTAssertLessThan(
MessageReplySwipePolicy.offset(locked: false, translation: CGSize(width: -24, height: 0)),
0
)
}
func testVisualOffsetIsCapped() {
XCTAssertEqual(
MessageReplySwipePolicy.offset(locked: true, translation: CGSize(width: -500, height: 0)),
-MessageReplySwipePolicy.maximumOffset
)
}
func testCanLockRequiresClearHorizontalStart() {
XCTAssertTrue(MessageReplySwipePolicy.canLock(CGSize(width: -24, height: 10)))
XCTAssertTrue(MessageReplySwipePolicy.canLock(CGSize(width: 24, height: 10)))
XCTAssertFalse(MessageReplySwipePolicy.canLock(CGSize(width: -30, height: 20)))
XCTAssertFalse(MessageReplySwipePolicy.canLock(CGSize(width: -8, height: 5)))
XCTAssertTrue(MessageReplySwipePolicy.canLock(CGSize(width: 40, height: 4)))
}
func testCanLockIsUnavailableOnceTheGestureTurnsVertical() {
// A scroll that arcs left after travelling down must never lock the
// swipe: the vertical travel already exceeds the lock budget.
XCTAssertFalse(MessageReplySwipePolicy.canLock(CGSize(width: -30, height: 40)))
XCTAssertFalse(MessageReplySwipePolicy.canLock(CGSize(width: -80, height: 60)))
}
func testLockedSwipeToleratesVerticalDrift() {
// Once locked the finger may drift: a 1.17 ratio would be rejected
// by the 1.6 lock dominance but must still count as a reply swipe.
XCTAssertTrue(MessageReplySwipePolicy.shouldReply(
locked: true,
translation: CGSize(width: -70, height: 60),
predictedEndTranslation: CGSize(width: -70, height: 60)
))
XCTAssertLessThan(
MessageReplySwipePolicy.offset(locked: true, translation: CGSize(width: -70, height: 60)),
0
)
}
func testRightwardDiagonalScrollDoesNotReply() {
XCTAssertFalse(MessageReplySwipePolicy.shouldReply(
locked: false,
translation: CGSize(width: 54, height: 44),
predictedEndTranslation: CGSize(width: 76, height: 58)
))
XCTAssertEqual(
MessageReplySwipePolicy.offset(locked: false, translation: CGSize(width: 54, height: 44)),
0
)
}
func testRightwardVisualOffsetIsCapped() {
XCTAssertEqual(
MessageReplySwipePolicy.offset(locked: true, translation: CGSize(width: 500, height: 0)),
MessageReplySwipePolicy.maximumOffset
)
}
func testRightwardIndicatorStaysHiddenUntilActivationDistance() {
XCTAssertEqual(
MessageReplySwipePolicy.offset(locked: false, translation: CGSize(width: 20, height: 0)),
0
)
XCTAssertGreaterThan(
MessageReplySwipePolicy.offset(locked: false, translation: CGSize(width: 24, height: 0)),
0
)
}
func testRightwardLockedSwipeToleratesVerticalDrift() {
XCTAssertTrue(MessageReplySwipePolicy.shouldReply(
locked: true,
translation: CGSize(width: 70, height: 60),
predictedEndTranslation: CGSize(width: 70, height: 60)
))
XCTAssertGreaterThan(
MessageReplySwipePolicy.offset(locked: true, translation: CGSize(width: 70, height: 60)),
0
)
}
}