Files
iccery-v2-mac/Tests/ICCeryUITests/Milestone6CalibrationUITests.swift
gronodandDevin <158243242+devin-ai-integration[bot]@users.noreply.github.com> 9857ddb4d0
macOS CI / build-and-test (push) Failing after 48s
macOS CI / package (push) Skipped
test(m9): retry dropped calibration generate tap in UI test
Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-11 22:38:30 +01:00

145 lines
5.5 KiB
Swift

import Foundation
import XCTest
/// Milestone 6 — Stage 0 printer calibration UI acceptance.
///
/// Uses the mock Argyll fixtures and UI-test environment flags so no real
/// instrument, printer, or modal file panel is required.
@MainActor
final class Milestone6CalibrationUITests: XCTestCase {
private var app: XCUIApplication!
private var testWorkDir: URL!
override func setUp() async throws {
continueAfterFailure = false
testWorkDir = FileManager.default.temporaryDirectory
.appendingPathComponent("cal-ui-test-\(UUID().uuidString)")
try FileManager.default.createDirectory(
at: testWorkDir,
withIntermediateDirectories: true
)
let binaryDir = URL(fileURLWithPath: #filePath)
.deletingLastPathComponent()
.appendingPathComponent("Fixtures/bin")
app = XCUIApplication()
app.launchEnvironment = [
"ICCERY_UI_TESTING": "1",
"ICCERY_ARGYLL_BINARY_DIR": binaryDir.path,
"ICCERY_TEST_WORKDIR": testWorkDir.path
]
app.launch()
app.activate()
}
override func tearDown() async throws {
app?.terminate()
app = nil
if let testWorkDir {
try? FileManager.default.removeItem(at: testWorkDir)
}
}
func testCalibrationDashboardOpensAndCanGenerate() throws {
// Set up a target and working directory on Stage 1.
let basename = app.textFields["targetBasename"]
XCTAssertTrue(basename.waitForExistence(timeout: 5))
basename.tap()
basename.typeText("DemoTarget")
let workDir = app.buttons["btnSelectWorkDir"]
XCTAssertTrue(workDir.waitForExistence(timeout: 5))
workDir.tap()
let generate = app.buttons["btnGenerate"]
XCTAssertTrue(generate.waitForExistence(timeout: 5))
generate.tap()
// Open the calibration dashboard once Stage 2 is reached.
let advance = app.buttons["btnAdvanceToStage3"]
XCTAssertTrue(advance.waitForExistence(timeout: 10))
let calButton = app.buttons["btnCalibratePrinter"]
XCTAssertTrue(calButton.waitForExistence(timeout: 5))
calButton.tap()
XCTAssertTrue(app.staticTexts["Calibrate Printer"].waitForExistence(timeout: 5))
// Start the calibration wedge. The mock targen will create CAL_DemoTarget.ti1.
let calGenerate = app.buttons["btnCalGenerate"]
XCTAssertTrue(calGenerate.waitForExistence(timeout: 5))
calGenerate.tap()
// After generation the wizard should advance to Stage 2 (layout) because
// a CAL_ .ti1 now exists and the session is in calibration mode.
let layout = app.buttons["btnCreateLayout"]
if !layout.waitForExistence(timeout: 25) {
// The generate tap can be dropped while the dashboard is still
// settling after the stage transition; retry once before failing.
if calGenerate.waitForExistence(timeout: 2) {
calGenerate.tap()
}
XCTAssertTrue(layout.waitForExistence(timeout: 25))
}
}
/// A failing calibration targen surfaces the error through the
/// wizard notice and restores the original basename (issue #80).
func testCalibrationTargenFailureRestoresBasename() throws {
let testRoot = FileManager.default.temporaryDirectory
.appendingPathComponent("cal-fail-\(UUID().uuidString)")
let appData = testRoot.appendingPathComponent("AppData")
try FileManager.default.createDirectory(
at: appData, withIntermediateDirectories: true)
defer { try? FileManager.default.removeItem(at: testRoot) }
// Pre-stage wizard state so the failing mock targen is only
// exercised by the calibration run, not target generation.
let state: [String: Any] = [
"currentStage": 1,
"basename": "DemoTarget",
"cwd": testWorkDir.path,
"sessionMode": "profile",
"calibrationOriginalBasename": ""
]
let stateURL = appData.appendingPathComponent("wizard_state.json")
try JSONSerialization.data(withJSONObject: state).write(to: stateURL)
app.terminate()
app.launchEnvironment["ICCERY_TEST_ROOT"] = testRoot.path
app.launchEnvironment["ICCERY_MOCK_TARGEN_EXIT"] = "2"
app.launch()
app.activate()
let calButton = app.buttons["btnCalibratePrinter"]
XCTAssertTrue(calButton.waitForExistence(timeout: 10))
calButton.tap()
let calGenerate = app.buttons["btnCalGenerate"]
XCTAssertTrue(calGenerate.waitForExistence(timeout: 10))
calGenerate.tap()
let notice = app.descendants(matching: .any)["noticeText"]
XCTAssertTrue(notice.waitForExistence(timeout: 20))
XCTAssertTrue((notice.value as? String ?? "")
.contains("Calibration target failed"))
// The pre-CAL_ basename is restored and persisted.
let deadline = Date().addingTimeInterval(10)
var restoredBasename: String?
while Date() < deadline {
if let data = try? Data(contentsOf: stateURL),
let object = try? JSONSerialization.jsonObject(with: data) as? [String: Any],
let basename = object["basename"] as? String {
restoredBasename = basename
if basename == "DemoTarget" { break }
}
RunLoop.current.run(until: Date().addingTimeInterval(0.1))
}
XCTAssertEqual(restoredBasename, "DemoTarget")
}
}