EchoUITests/TranscriptJumpUITests.swift
Rama main · réplica de lectura del repositorio original.
import XCTest
/// "Jump to latest" has to bring back the newest message after fast flings. XCUITest waits
/// for the list to settle before each tap, so a tap during momentum can't be simulated here;
/// these cover what broke it: the button vanishing mid-fling and long jumps landing short.
@MainActor
final class TranscriptJumpUITests: XCTestCase {
private func launchLongDemo() -> XCUIApplication {
continueAfterFailure = false
let app = XCUIApplication()
// Launch arguments land in UserDefaults' argument domain: skip setup, stay on the transcript.
app.launchArguments = ["-echo.demoLong"] + XCUIApplication.chatsSection + XCUIApplication.straightToChat
app.launch()
XCTAssertTrue(app.staticTexts["End of the long demo."].waitForExistence(timeout: 15), "The long demo didn't open at its end")
return app
}
/// Opened from a reply's notification: at the reply's first line, not its end (GitHub #63),
/// with Jump to latest for the rest.
func testOpenedFromAReplyStartsAtItsTop() {
continueAfterFailure = false
let app = XCUIApplication()
app.launchArguments = ["-echo.demoHeavy", "3", "-echo.fromReply"] + XCUIApplication.chatsSection + XCUIApplication.straightToChat
app.launch()
let jump = app.buttons["Jump to the newest message"]
XCTAssertTrue(jump.waitForExistence(timeout: 15), "It opened at the end of the reply")
let asked = app.staticTexts.matching(NSPredicate(format: "label BEGINSWITH 'Turn 3'")).firstMatch
XCTAssertTrue(asked.exists && asked.frame.maxY < app.frame.midY, "The question the reply answers isn't just above it")
}
func testJumpToLatestReachesTheEndAtRest() {
let app = launchLongDemo()
let end = app.staticTexts["End of the long demo."]
let transcript = app.scrollViews.firstMatch
transcript.swipeDown(velocity: .fast)
transcript.swipeDown(velocity: .fast)
let jump = app.buttons["Jump to the newest message"]
XCTAssertTrue(jump.waitForExistence(timeout: 5), "No Jump to latest after scrolling up")
jump.tap()
XCTAssertTrue(end.waitForExistence(timeout: 5), "The arrow didn't bring back the newest message")
XCTAssertTrue(end.isHittable, "The newest message exists but isn't on screen")
}
func testJumpToLatestReachesTheEndAfterLongFlings() {
let app = launchLongDemo()
let end = app.staticTexts["End of the long demo."]
let transcript = app.scrollViews.firstMatch
// Read back up the transcript so the arrow appears.
transcript.swipeDown(velocity: .fast)
transcript.swipeDown(velocity: .fast)
let jump = app.buttons["Jump to the newest message"]
XCTAssertTrue(jump.waitForExistence(timeout: 5), "No Jump to latest after scrolling up")
// A screen point captured earlier, so the tap goes where the arrow was even if it vanished.
let frame = jump.frame
let target = app.coordinate(withNormalizedOffset: .zero).withOffset(CGVector(dx: frame.midX, dy: frame.midY))
// Fling far up the transcript, then hit the arrow.
transcript.swipeDown(velocity: 3000)
target.tap()
XCTAssertTrue(end.waitForExistence(timeout: 5), "The arrow didn't bring back the newest message")
XCTAssertTrue(end.isHittable, "The newest message exists but isn't on screen")
}
/// Scrolled back to the end by hand, the pill has nothing left to offer and goes.
func testJumpToLatestGoesOnceTheEndIsReachedByHand() {
let app = launchLongDemo()
let end = app.staticTexts["End of the long demo."]
let transcript = app.scrollViews.firstMatch
transcript.swipeDown(velocity: .fast)
let jump = app.buttons["Jump to the newest message"]
XCTAssertTrue(jump.waitForExistence(timeout: 5), "No Jump to latest after scrolling up")
for _ in 0 ..< 6 where !end.isHittable { transcript.swipeUp(velocity: .fast) }
XCTAssertTrue(end.isHittable, "Swiping didn't reach the end")
XCTAssertTrue(jump.waitForNonExistence(timeout: 3), "Jump to latest is still there at the end")
// A touch on the transcript at its end doesn't bring it back.
transcript.swipeUp(velocity: .slow)
XCTAssertFalse(jump.exists, "A swipe at the end brought Jump to latest back")
}
}