EchoUITests/MoreCardsUITests.swift
Rama main · réplica de lectura del repositorio original.
import XCTest
/// The home, reminder, comparison and score cards (asked 2026-10-30), from `-echo.demoCards
/// home|reminder|compare|score`. With `TEST_RUNNER_SHOT_DIR` set, the screens are written there too
/// (`SHOT_NAME` before each name), for looking at.
@MainActor
final class MoreCardsUITests: XCTestCase {
private func launch(_ kind: String, waitingFor text: String) -> XCUIApplication {
continueAfterFailure = false
let app = XCUIApplication()
app.launchArguments = ["-echo.demoCards", kind, "-openToVoiceScreen", "NO", "-listenOnOpen", "NO", "-requireBiometrics", "NO"]
app.launch()
XCTAssertTrue(app.text(containing: text).waitForExistence(timeout: 20), "The demo reply didn't appear")
return app
}
private func scrollUp(_ app: XCUIApplication, until element: XCUIElement) {
for _ in 0 ..< 5 where !element.isHittable { app.windows.firstMatch.swipeDown() }
sleep(1)
}
func testHomeAsksTheAgentAndConfirmsAnUnlock() {
let app = launch("home", waitingFor: "The garage is closed")
scrollUp(app, until: app.text(containing: "Downstairs"))
XCTAssertTrue(app.text(containing: "Kitchen · On · 80%").exists, "A light's state and brightness from 0–255 aren't shown")
shot(app, "home-top")
// The button says which device to VoiceOver (UAT 2.3.1); the question's own button is "Unlock".
app.buttons["Unlock Front door"].tap()
XCTAssertTrue(app.buttons["Unlock"].waitForExistence(timeout: 5) && app.staticTexts["Unlock Front door?"].waitForExistence(timeout: 5),
"Unlocking didn't ask first")
shot(app, "home-confirm")
app.text(containing: "Kitchen · On").coordinate(withNormalizedOffset: CGVector(dx: 0.3, dy: 0.5)).tap() // outside the question: not unlocked
sleep(1)
XCTAssertFalse(app.text(containing: "Unlock Front door").exists, "Unlock was sent")
let toggle = app.switches["Kitchen lights"]
XCTAssertTrue(toggle.isHittable, "The kitchen's switch isn't on the screen")
(toggle.switches.firstMatch.exists ? toggle.switches.firstMatch : toggle).tap()
XCTAssertTrue(app.text(containing: "Turn off Kitchen lights").waitForExistence(timeout: 5), "The switch didn't ask the agent")
shot(app, "home-asked")
}
func testRemindersCountDownAndAskToChange() {
let app = launch("reminder", waitingFor: "the pasta timer is running")
scrollUp(app, until: app.text(containing: "Pasta"))
XCTAssertTrue(app.text(containing: "Ends at").exists, "The timer doesn't say when it ends")
shot(app, "reminder-top")
app.windows.firstMatch.swipeUp()
sleep(1)
XCTAssertTrue(app.text(containing: "Every Monday at 9 AM").exists, "How it repeats isn't shown")
app.buttons["Change…"].firstMatch.tap()
XCTAssertTrue(app.textFields.firstMatch.waitForExistence(timeout: 5), "Change… has no field")
shot(app, "reminder-change")
}
func testAComparisonOfTwoAndOfThree() {
let app = launch("compare", waitingFor: "Madeira, if you want")
scrollUp(app, until: app.text(containing: "A first language"))
XCTAssertTrue(app.text(containing: "For you: Python").exists, "The verdict isn't shown")
app.buttons.containing(NSPredicate(format: "label BEGINSWITH %@", "Python")).firstMatch.tap()
XCTAssertTrue(app.text(containing: "Reads almost like English").waitForExistence(timeout: 5), "An option's pros don't open")
shot(app, "compare-two")
for _ in 0 ..< 5 where !app.text(containing: "Getting there").isHittable { app.windows.firstMatch.swipeUp() }
sleep(1)
shot(app, "compare-three")
}
func testGamesOverToComeAndBeingPlayed() {
let app = launch("score", waitingFor: "Tampa leads")
XCTAssertTrue(app.buttons["Refresh"].exists, "A live game has no Refresh")
shot(app, "score-live")
scrollUp(app, until: app.text(containing: "Final"))
shot(app, "score-top")
}
private func shot(_ app: XCUIApplication, _ name: String) {
let screen = XCUIScreen.main.screenshot()
let attachment = XCTAttachment(screenshot: screen)
attachment.name = name
attachment.lifetime = .keepAlways
add(attachment)
let environment = ProcessInfo.processInfo.environment
if let folder = environment["SHOT_DIR"] {
try? screen.pngRepresentation.write(to: URL(fileURLWithPath: folder).appending(path: (environment["SHOT_NAME"] ?? "") + name + ".png"))
}
}
}