ios: simplify Agent transcript positioning and entrances
TestFlight / Build and upload (push) Successful in 1m59s
TestFlight / Build and upload (push) Successful in 1m59s
This commit is contained in:
@@ -55,6 +55,79 @@ final class TranscriptFadeUITests: XCTestCase {
|
||||
return try XCTUnwrap(JSONSerialization.jsonObject(with: data) as? [String: Any])
|
||||
}
|
||||
|
||||
private func reloadMixedHistory() async throws {
|
||||
app.terminate()
|
||||
let rows = (1...160).map { index in
|
||||
let short = "History message \(index): local simulator fixture."
|
||||
return ["role": index % 3 == 0 ? "user" : "assistant",
|
||||
"content": index == 160 || index % 3 == 0 ? short :
|
||||
"### Investigation \(index)\n\n" + String(repeating: "A longer transcript paragraph with **emphasis** and `inline code`.\n\n", count: 4) +
|
||||
"- Preserve visible content.\n- Keep the composer available.\n\n```swift\nrender(messages[\(index)])\n```"]
|
||||
}
|
||||
try await control(["action": "presentation-samples", "messages": rows])
|
||||
app.launch()
|
||||
}
|
||||
|
||||
func testInitialOpenAndTabReturnShowLatestWithoutScrolling() async throws {
|
||||
try await reloadMixedHistory()
|
||||
openAgent()
|
||||
let latest = app.staticTexts["History message 160: local simulator fixture."]
|
||||
XCTAssertTrue(latest.isHittable)
|
||||
XCTAssertLessThan(latest.frame.maxY, composer.frame.minY)
|
||||
capture("agent-initial-open")
|
||||
|
||||
showSidebar()
|
||||
app.buttons["Settings"].tap()
|
||||
XCTAssertFalse(composer.exists)
|
||||
openAgent()
|
||||
XCTAssertTrue(latest.isHittable, "Returning to Agent must not need a scroll to materialize rows")
|
||||
XCTAssertLessThan(latest.frame.maxY, composer.frame.minY)
|
||||
capture("agent-tab-return")
|
||||
}
|
||||
|
||||
func testSendClearsMultilineComposerAndKeepsLatestAboveKeyboard() async throws {
|
||||
try await reloadMixedHistory()
|
||||
openAgent()
|
||||
composer.tap()
|
||||
if let existing = composer.value as? String, !existing.isEmpty, existing != "Enter Prompt" {
|
||||
composer.press(forDuration: 1)
|
||||
let selectAll = app.descendants(matching: .any).matching(NSPredicate(format: "label == %@", "Select All")).firstMatch
|
||||
if selectAll.waitForExistence(timeout: 2) { selectAll.tap() }
|
||||
else { composer.typeText(String(repeating: XCUIKeyboardKey.rightArrow.rawValue, count: existing.count)) }
|
||||
composer.typeText(String(repeating: XCUIKeyboardKey.delete.rawValue, count: existing.count))
|
||||
}
|
||||
let draft = "Keyboard send\nsecond line\nthird line"
|
||||
composer.typeText(draft)
|
||||
XCTAssertTrue(app.keyboards.firstMatch.exists)
|
||||
let multilineHeight = composer.frame.height
|
||||
app.buttons["agent-send"].tap()
|
||||
let cleared = XCTNSPredicateExpectation(predicate: NSPredicate(format: "value == %@ OR value == %@", "", "Enter Prompt"), object: composer)
|
||||
await fulfillment(of: [cleared], timeout: 5)
|
||||
XCTAssertLessThan(composer.frame.height, multilineHeight)
|
||||
XCTAssertTrue(app.keyboards.firstMatch.exists)
|
||||
let sent = app.staticTexts[draft]
|
||||
XCTAssertTrue(sent.waitForExistence(timeout: 5))
|
||||
XCTAssertTrue(sent.isHittable)
|
||||
let reply = app.staticTexts.containing(NSPredicate(format: "label CONTAINS %@", "Finished: Keyboard send")).firstMatch
|
||||
let followed = XCTNSPredicateExpectation(predicate: NSPredicate(format: "hittable == true"), object: reply)
|
||||
await fulfillment(of: [followed], timeout: 10)
|
||||
capture("agent-send-cleared-composer-with-keyboard")
|
||||
XCTAssertGreaterThan(reply.frame.minY, transcript.frame.minY + 64)
|
||||
XCTAssertLessThan(reply.frame.maxY, composer.frame.minY)
|
||||
// Finished: is only the first Markdown paragraph. Measure the final
|
||||
// reply content, leaving the same allowance for metadata and spacing.
|
||||
let replyEnd = app.staticTexts["The local fixture returned three matches."]
|
||||
XCTAssertTrue(replyEnd.isHittable)
|
||||
XCTAssertLessThan(replyEnd.frame.maxY, composer.frame.minY)
|
||||
let bottomGap = composer.frame.minY - replyEnd.frame.maxY
|
||||
print("Agent send settled final-content gap: \(bottomGap)pt")
|
||||
XCTAssertLessThan(bottomGap, 100, "Composer clearing must not leave the transcript shifted above the bottom")
|
||||
XCTAssertTrue(app.buttons["agent-attach"].isHittable)
|
||||
try await Task.sleep(for: .milliseconds(500))
|
||||
let read = try await control(["action": "state"])
|
||||
XCTAssertEqual(read["readCursor"] as? Int, read["cursor"] as? Int)
|
||||
}
|
||||
|
||||
func testSharedHeaderFadeGeometry() async throws {
|
||||
showSidebar()
|
||||
let chat = app.buttons.containing(NSPredicate(format: "label CONTAINS %@", "Transcript fade comparison")).firstMatch
|
||||
|
||||
Reference in New Issue
Block a user