import XCTest @MainActor final class NativeUITests: XCTestCase { func testCreateAndEditFormula() { continueAfterFailure = false let app = XCUIApplication() app.launch() defer { app.terminate() } let create = app.buttons["New spreadsheet"] XCTAssertTrue(create.waitForExistence(timeout: 15)) create.tap() let formula = app.textFields["Cell contents or formula"] XCTAssertTrue(formula.waitForExistence(timeout: 10), "Creating a sheet must navigate to its native editor") formula.tap() formula.typeText("=2+3") app.buttons["Save"].tap() XCTAssertTrue(app.buttons["A1, 5"].waitForExistence(timeout: 10), "The server-calculated value must appear") let saved = NSPredicate(format: "exists == false") XCTAssertEqual(XCTWaiter.wait(for: [XCTNSPredicateExpectation(predicate: saved, object: app.buttons["Save"])], timeout: 5), .completed) app.buttons["A1, 5"].tap() let rawFormula = NSPredicate(format: "value == %@", "=2+3") XCTAssertEqual(XCTWaiter.wait(for: [XCTNSPredicateExpectation(predicate: rawFormula, object: formula)], timeout: 5), .completed, "Selecting a cell must expose its formula rather than its display value") formula.coordinate(withNormalizedOffset: CGVector(dx: 0.95, dy: 0.5)).tap() formula.typeText(String(repeating: XCUIKeyboardKey.delete.rawValue, count: 4)) formula.typeText("=7*6") app.buttons["Save"].tap() XCTAssertTrue(app.buttons["A1, 42"].waitForExistence(timeout: 10)) XCTAssertEqual(XCTWaiter.wait(for: [XCTNSPredicateExpectation(predicate: saved, object: app.buttons["Save"])], timeout: 5), .completed) app.buttons["A1, 42"].tap() let finalFormula = NSPredicate(format: "value == %@", "=7*6") XCTAssertEqual(XCTWaiter.wait(for: [XCTNSPredicateExpectation(predicate: finalFormula, object: formula)], timeout: 5), .completed) // Exercise commands through the actual native menus, preserving A1 as the // fixture's independent server-persistence sentinel. menu(app, "Edit", command: "Fill down") XCTAssertTrue(app.buttons["A2, 42"].waitForExistence(timeout: 10)) select(app, "A1:A2") menu(app, "Edit", command: "Copy") select(app, "B1") menu(app, "Edit", command: "Paste") XCTAssertTrue(app.buttons["B1, 42"].waitForExistence(timeout: 10)) XCTAssertTrue(app.buttons["B2, 42"].waitForExistence(timeout: 10)) select(app, "B1:B2") openMenu(app, "Format") app.buttons["Number format"].tap() app.buttons["Number"].tap() XCTAssertTrue(app.buttons["B1, 42.00"].waitForExistence(timeout: 10)) XCTAssertTrue(app.buttons["B2, 42.00"].waitForExistence(timeout: 10)) menu(app, "Edit", command: "Undo my last value edit") XCTAssertTrue(app.buttons["B2, Empty"].waitForExistence(timeout: 10)) select(app, "B2") XCTAssertEqual(XCTWaiter.wait(for: [XCTNSPredicateExpectation(predicate: NSPredicate(format: "value == %@ OR value == %@", "", "Cell contents or formula"), object: formula)], timeout: 10), .completed) menu(app, "File", command: "Version history") let restore = app.buttons["Restore before this edit"].firstMatch XCTAssertTrue(restore.waitForExistence(timeout: 10)) restore.tap() app.buttons["Done"].tap() // Canonical value undo clears the sparse cell row, including its format; // restoring the input therefore returns the default number display. XCTAssertTrue(app.buttons["B2, 42"].waitForExistence(timeout: 10), "History Restore must restore the pasted formula") select(app, "A1") let screenshot = XCTAttachment(screenshot: app.screenshot()) screenshot.name = "Sheets native formula editing" screenshot.lifetime = .keepAlways add(screenshot) } private func select(_ app: XCUIApplication, _ reference: String) { let field = app.textFields["Cell or range, for example A1:B5"] XCTAssertTrue(field.waitForExistence(timeout: 5)) field.coordinate(withNormalizedOffset: CGVector(dx: 0.95, dy: 0.5)).tap() field.typeText(String(repeating: XCUIKeyboardKey.delete.rawValue, count: (field.value as? String ?? "").count)) field.typeText(reference + "\n") } func testFailedCellEditCanBeRetriedWithoutLosingDraft() { continueAfterFailure = false let app = XCUIApplication() app.launch() defer { app.terminate() } XCTAssertTrue(app.buttons["New spreadsheet"].waitForExistence(timeout: 15)) app.buttons["New spreadsheet"].tap() let formula = app.textFields["Cell contents or formula"] XCTAssertTrue(formula.waitForExistence(timeout: 10)) formula.tap() // Only this exact synthetic input triggers one refusal in the fixture. formula.typeText("=6*7") app.buttons["Save"].tap() let retry = app.buttons["Retry pending edits"] XCTAssertTrue(retry.waitForExistence(timeout: 10)) XCTAssertEqual(formula.value as? String, "=6*7") XCTAssertFalse(formula.isEnabled) app.buttons["A2, Empty"].tap() XCTAssertEqual(app.textFields["Cell or range, for example A1:B5"].value as? String, "A1") retry.tap() XCTAssertTrue(app.buttons["A1, 42"].waitForExistence(timeout: 10)) XCTAssertEqual(XCTWaiter.wait(for: [XCTNSPredicateExpectation(predicate: NSPredicate(format: "exists == false"), object: retry)], timeout: 10), .completed) let screenshot = XCTAttachment(screenshot: app.screenshot()) screenshot.name = "Sheets native retried edit"; screenshot.lifetime = .keepAlways; add(screenshot) } func testExportWorkbookOpensNativeDestinationAndCancels() { continueAfterFailure = false let app = XCUIApplication() app.launch() defer { app.terminate() } let workbook = app.buttons["Native review workbook"] XCTAssertTrue(workbook.waitForExistence(timeout: 15)) workbook.tap() XCTAssertTrue(app.textFields["Cell contents or formula"].waitForExistence(timeout: 10)) menu(app, "File", command: "Export workbook") let export = app.buttons["Save workbook…"] XCTAssertTrue(export.waitForExistence(timeout: 10)) export.tap() let cancel = app.buttons["Cancel"] XCTAssertTrue(cancel.waitForExistence(timeout: 15), "A native file destination picker must open after download") let screenshot = XCTAttachment(screenshot: app.screenshot()) screenshot.name = "Sheets native export destination" screenshot.lifetime = .keepAlways add(screenshot) cancel.tap() XCTAssertTrue(export.waitForExistence(timeout: 10)) app.buttons["Done"].tap() } private func openMenu(_ app: XCUIApplication, _ name: String) { if app.buttons["Sheet actions"].exists { app.buttons["Sheet actions"].tap() } let menu = app.buttons[name] XCTAssertTrue(menu.waitForExistence(timeout: 5), "Missing native menu: \(name)") menu.tap() } private func menu(_ app: XCUIApplication, _ name: String, command: String) { openMenu(app, name) let action = app.buttons[command] XCTAssertTrue(action.waitForExistence(timeout: 5), "Missing native command: \(command)") action.tap() } }