EchoUITests/SwipeToConversationsUITests.swift
Rama main · réplica de lectura del repositorio original.
import XCTest
/// iPhone: a swipe to the right on the chat opens the conversation list, and the transcript
/// still scrolls up and down.
@MainActor
final class SwipeToConversationsUITests: XCTestCase {
private func launch(pinSection: Bool = true) -> XCUIApplication {
continueAfterFailure = false
let app = XCUIApplication()
app.launchArguments = (pinSection ? XCUIApplication.chatsSection : []) + XCUIApplication.straightToChat
+ ["-echo.demo", "-transport", "chatCompletions"]
app.launch()
return app
}
private func drag(_ app: XCUIApplication, from: CGVector, to: CGVector) {
let window = app.windows.firstMatch
window.coordinate(withNormalizedOffset: from)
.press(forDuration: 0.05, thenDragTo: window.coordinate(withNormalizedOffset: to), withVelocity: .fast,
thenHoldForDuration: 0)
}
func testSwipeRightOpensConversations() throws {
let app = launch()
try XCTSkipIf(app.windows.firstMatch.frame.width > 600, "iPad keeps the list in the sidebar")
XCTAssertTrue(app.buttons["Conversations"].waitForExistence(timeout: 15), "The chat never appeared")
drag(app, from: CGVector(dx: 0.1, dy: 0.45), to: CGVector(dx: 0.9, dy: 0.47))
XCTAssertTrue(app.navigationBars["Conversations"].waitForExistence(timeout: 5), "Swiping right didn't open the list")
}
/// One tap on Cron or Kanban switches the list; it took two.
func testOneTapSwitchesSection() throws {
// Not pinned: a launch-argument value can't be overwritten, so no tap could change it.
let app = launch(pinSection: false)
try XCTSkipIf(app.windows.firstMatch.frame.width > 600, "iPad keeps the list in the sidebar")
XCTAssertTrue(app.buttons["Conversations"].waitForExistence(timeout: 15), "The chat never appeared")
app.buttons["Conversations"].tap()
let segments = app.segmentedControls.firstMatch
XCTAssertTrue(segments.waitForExistence(timeout: 5), "The button didn't open the list")
sleep(1)
for (segment, title) in [("Cron", "Cron"), ("Kanban", "Kanban"), ("Chats", "Conversations"), ("Kanban", "Kanban"), ("Cron", "Cron")] {
segments.buttons[segment].tap()
XCTAssertTrue(app.navigationBars[title].waitForExistence(timeout: 3), "One tap on \(segment) didn't switch")
}
}
/// The same, straight after a swipe opens the panel.
func testOneTapSwitchesSectionAfterASwipe() throws {
let app = launch(pinSection: false)
try XCTSkipIf(app.windows.firstMatch.frame.width > 600, "iPad keeps the list in the sidebar")
XCTAssertTrue(app.buttons["Conversations"].waitForExistence(timeout: 15), "The chat never appeared")
for (segment, title) in [("Chats", "Conversations"), ("Cron", "Cron"), ("Kanban", "Kanban"), ("Chats", "Conversations")] {
drag(app, from: CGVector(dx: 0.1, dy: 0.45), to: CGVector(dx: 0.9, dy: 0.47))
let segments = app.segmentedControls.firstMatch
XCTAssertTrue(segments.waitForExistence(timeout: 5), "Swiping right didn't open the list")
segments.buttons[segment].tap()
XCTAssertTrue(app.navigationBars[title].waitForExistence(timeout: 3), "One tap on \(segment) didn't switch")
app.windows.firstMatch.coordinate(withNormalizedOffset: CGVector(dx: 0.95, dy: 0.5)).tap() // close
sleep(1)
}
}
/// The panel closes from the dimmed chat beside it, and when a conversation is picked.
func testPanelCloses() throws {
let app = launch()
try XCTSkipIf(app.windows.firstMatch.frame.width > 600, "iPad keeps the list in the sidebar")
XCTAssertTrue(app.buttons["Conversations"].waitForExistence(timeout: 15), "The chat never appeared")
let list = app.navigationBars["Conversations"]
app.buttons["Conversations"].tap()
XCTAssertTrue(list.waitForExistence(timeout: 5), "The button didn't open the list")
app.windows.firstMatch.coordinate(withNormalizedOffset: CGVector(dx: 0.95, dy: 0.5)).tap()
XCTAssertTrue(list.waitForNonExistence(timeout: 5), "Tapping the chat beside the panel didn't close it")
drag(app, from: CGVector(dx: 0.1, dy: 0.45), to: CGVector(dx: 0.9, dy: 0.47))
XCTAssertTrue(list.waitForExistence(timeout: 5), "Swiping right didn't open the list")
drag(app, from: CGVector(dx: 0.95, dy: 0.5), to: CGVector(dx: 0.2, dy: 0.5))
XCTAssertTrue(list.waitForNonExistence(timeout: 5), "Dragging the chat back didn't close the panel")
app.buttons["Conversations"].tap()
XCTAssertTrue(list.waitForExistence(timeout: 5), "The button didn't open the list")
list.buttons["New conversation"].tap()
XCTAssertTrue(list.waitForNonExistence(timeout: 5), "Starting a new conversation didn't close the panel")
}
/// A swipe too short to open the panel leaves it parked: its bar (Settings, New conversation)
/// must not stay reachable off screen.
func testShortSwipeLeavesThePanelClosed() throws {
let app = launch()
try XCTSkipIf(app.windows.firstMatch.frame.width > 600, "iPad keeps the list in the sidebar")
XCTAssertTrue(app.buttons["Conversations"].waitForExistence(timeout: 15), "The chat never appeared")
let window = app.windows.firstMatch
window.coordinate(withNormalizedOffset: CGVector(dx: 0.1, dy: 0.45))
.press(forDuration: 0.05, thenDragTo: window.coordinate(withNormalizedOffset: CGVector(dx: 0.25, dy: 0.45)),
withVelocity: .slow, thenHoldForDuration: 0.2)
XCTAssertFalse(app.navigationBars["Conversations"].waitForExistence(timeout: 2), "A short swipe opened the list")
}
func testVerticalScrollDoesNotOpenConversations() throws {
let app = launch()
try XCTSkipIf(app.windows.firstMatch.frame.width > 600, "iPad keeps the list in the sidebar")
XCTAssertTrue(app.buttons["Conversations"].waitForExistence(timeout: 15), "The chat never appeared")
drag(app, from: CGVector(dx: 0.4, dy: 0.3), to: CGVector(dx: 0.5, dy: 0.7))
XCTAssertFalse(app.navigationBars["Conversations"].waitForExistence(timeout: 2), "A scroll opened the list")
}
}