// // SmokeTests.swift // PrismeUITests // // Author: Simon-Pierre Boucher // import XCTest /// End-to-end smoke tests for the bare browser: address bar intents, /// search-engine proposals, and actual page loads. Proposals are confirmed /// by tapping โ€” exactly the designed interaction โ€” because a hardware /// Return key press can be routed to focused buttons instead of the field. final class SmokeTests: XCTestCase { override func setUp() { continueAfterFailure = false } @MainActor private func startEditing(_ app: XCUIApplication) -> XCUIElement { let compact = app.buttons["addressBar.compact"] XCTAssertTrue(compact.waitForExistence(timeout: 5)) compact.tap() let field = app.textFields["addressBar.field"] if !field.waitForExistence(timeout: 3) { // A tap landing mid-launch-animation can be swallowed; retry once. compact.tap() } XCTAssertTrue(field.waitForExistence(timeout: 5)) field.tap() return field } @MainActor func testNavigateToURLLoadsPage() throws { let app = XCUIApplication() app.launch() let field = startEditing(app) field.typeText("example.com") let navigate = app.buttons["proposal.navigate"] XCTAssertTrue(navigate.waitForExistence(timeout: 5)) navigate.tap() XCTAssertTrue(app.webViews.firstMatch.waitForExistence(timeout: 10)) let pageText = app.webViews.staticTexts["Example Domain"] XCTAssertTrue(pageText.waitForExistence(timeout: 20)) XCTAssertTrue(app.buttons["addressBar.compact"].label.contains("example.com")) } @MainActor func testSearchProposalsOfferBothEngines() throws { let app = XCUIApplication() app.launch() let field = startEditing(app) field.typeText("chat noir") // Both engines must be proposed on every query. XCTAssertTrue(app.buttons["proposal.search.duckDuckGo"].waitForExistence(timeout: 5)) XCTAssertTrue(app.buttons["proposal.search.google"].exists) } @MainActor func testReaderSemanticZoomLevels() throws { let app = XCUIApplication() app.launch() let field = startEditing(app) field.typeText("example.com") app.buttons["proposal.navigate"].tap() XCTAssertTrue(app.webViews.staticTexts["Example Domain"].waitForExistence(timeout: 20)) // The understanding strip appears once the page is distilled; // it is the main entry into the reader. let strip = app.buttons["insight.read"] XCTAssertTrue(strip.waitForExistence(timeout: 10)) attachScreenshot(named: "insight-strip") strip.tap() XCTAssertTrue(app.buttons["reader.level.Texte"].waitForExistence(timeout: 5)) // Full text renders the page's blocks natively. XCTAssertTrue(app.staticTexts["Example Domain"].waitForExistence(timeout: 5)) attachScreenshot(named: "reader-texte") // Outline lists the page's headings. app.buttons["reader.level.Plan"].tap() XCTAssertTrue(app.staticTexts["Example Domain"].waitForExistence(timeout: 5)) // Gist level always resolves โ€” model or deterministic fallback. // (The container identifier cascades to the gist's text elements.) app.buttons["reader.level.Essentiel"].tap() XCTAssertTrue(app.staticTexts["reader.gist"].firstMatch.waitForExistence(timeout: 5)) attachScreenshot(named: "reader-essentiel") // Closing returns to the raw page (ยง7). app.buttons["reader.close"].tap() XCTAssertTrue(app.webViews.firstMatch.waitForExistence(timeout: 5)) } @MainActor func testSemanticHistoryRecallInAddressBar() throws { let app = XCUIApplication() app.launch() // Visit a page so the history has something to remember. var field = startEditing(app) field.typeText("example.com") app.buttons["proposal.navigate"].tap() XCTAssertTrue(app.webViews.staticTexts["Example Domain"].waitForExistence(timeout: 20)) // Recording happens shortly after the load settles. Thread.sleep(forTimeInterval: 2.5) // From a fresh tab, typing recalls the visited page. app.buttons["plus"].tap() field = startEditing(app) field.typeText("example domain") let recall = app.buttons["proposal.recall"].firstMatch XCTAssertTrue(recall.waitForExistence(timeout: 5)) attachScreenshot(named: "history-recall") recall.tap() XCTAssertTrue(app.webViews.staticTexts["Example Domain"].waitForExistence(timeout: 20)) } @MainActor func testStructuredFavoriteFromReaderAppearsInLibrary() throws { let app = XCUIApplication() app.launch() let field = startEditing(app) field.typeText("example.com") app.buttons["proposal.navigate"].tap() XCTAssertTrue(app.webViews.staticTexts["Example Domain"].waitForExistence(timeout: 20)) // Save from the reader: works with or without the local model. // (Second reader entry: the affordance in the address bar.) XCTAssertTrue(app.buttons["addressBar.reader"].waitForExistence(timeout: 5)) app.buttons["addressBar.reader"].tap() let save = app.buttons["reader.save"] XCTAssertTrue(save.waitForExistence(timeout: 5)) save.tap() app.buttons["reader.close"].tap() // The library lists the page as native data. app.buttons["books.vertical"].tap() XCTAssertTrue(app.buttons["Pages"].waitForExistence(timeout: 5)) app.buttons["Pages"].tap() let favorite = app.buttons["library.favorite"].firstMatch XCTAssertTrue(favorite.waitForExistence(timeout: 5)) XCTAssertTrue(app.staticTexts["Example Domain"].exists) attachScreenshot(named: "library-favorite") } @MainActor private func attachScreenshot(named name: String) { let attachment = XCTAttachment(screenshot: XCUIScreen.main.screenshot()) attachment.name = name attachment.lifetime = .keepAlways add(attachment) } @MainActor func testGoogleSearchLoadsGoogle() throws { let app = XCUIApplication() app.launch() let field = startEditing(app) field.typeText("chat noir") let google = app.buttons["proposal.search.google"] XCTAssertTrue(google.waitForExistence(timeout: 5)) google.tap() XCTAssertTrue(app.webViews.firstMatch.waitForExistence(timeout: 10)) let bar = app.buttons["addressBar.compact"] let onGoogle = NSPredicate(format: "label CONTAINS 'google'") expectation(for: onGoogle, evaluatedWith: bar) waitForExpectations(timeout: 15) } }