test(m10): combine gamut layer toggle AX; harden gallery wait on macOS 12 #159

Merged
gronod merged 1 commits from fix/m10-ci-ui-macos12 into milestone/m10-studio 2026-09-13 15:53:50 +01:00
2 changed files with 38 additions and 2 deletions
+4
View File
@@ -144,6 +144,10 @@ struct GamutView: View {
.toggleStyle(.checkbox) .toggleStyle(.checkbox)
.disabled(layer == nil || viewModel.viewerUnavailable) .disabled(layer == nil || viewModel.viewerUnavailable)
.help(layer.map { $0.sourceURL.lastPathComponent } ?? "No profile .gam loaded") .help(layer.map { $0.sourceURL.lastPathComponent } ?? "No profile .gam loaded")
// macOS 12 puts the identifier on the Toggle's container, an
// element that never reports isEnabled combine so the a11y
// leaf is the checkbox itself.
.accessibilityElement(children: .combine)
.accessibilityIdentifier("gamutLayer-\(id)") .accessibilityIdentifier("gamutLayer-\(id)")
} }
+34 -2
View File
@@ -85,6 +85,31 @@ final class Milestone2UITests: XCTestCase {
return el return el
} }
/// Exists **and** `isEnabled` guards clicks against buttons that
/// appear a beat before their `.disabled` condition clears.
private func waitUntilEnabled(_ id: String, timeout: TimeInterval = 10) -> XCUIElement {
let deadline = Date().addingTimeInterval(timeout)
while Date() < deadline {
let el = element(id)
if el.exists && el.isEnabled { return el }
RunLoop.current.run(until: Date().addingTimeInterval(0.1))
}
let el = element(id)
XCTAssertTrue(
el.exists && el.isEnabled, "Expected enabled element \(id)")
return el
}
/// Non-asserting existence poll for the retry-or-fail pattern.
private func existsAfter(_ id: String, timeout: TimeInterval) -> Bool {
let deadline = Date().addingTimeInterval(timeout)
while Date() < deadline {
if element(id).exists { return true }
RunLoop.current.run(until: Date().addingTimeInterval(0.1))
}
return element(id).exists
}
/// Assert an element stays absent after a short dwell unlike /// Assert an element stays absent after a short dwell unlike
/// `waitForExistence`, which always burns its full timeout on the /// `waitForExistence`, which always burns its full timeout on the
/// negative path. /// negative path.
@@ -181,8 +206,15 @@ final class Milestone2UITests: XCTestCase {
XCTAssertTrue(element("tiffDpi").exists) XCTAssertTrue(element("tiffDpi").exists)
XCTAssertTrue(element("targetLabelPreview").exists) XCTAssertTrue(element("targetLabelPreview").exists)
app.buttons["btnCreateLayout"].click() // On the slow macOS 12 runner a synthesized click can land
XCTAssertTrue(waitFor("galleryPage-0", timeout: 20).exists) // while the button is still rebuilding retry once if the
// gallery never materialises, then allow a generous window
// for the fixture printtarg + PNG render.
waitUntilEnabled("btnCreateLayout").click()
if !existsAfter("galleryPage-0", timeout: 15) {
waitUntilEnabled("btnCreateLayout").click()
}
XCTAssertTrue(waitFor("galleryPage-0", timeout: 30).exists)
XCTAssertTrue(FileManager.default.fileExists( XCTAssertTrue(FileManager.default.fileExists(
atPath: workDir.appendingPathComponent("mytarget.ti2").path)) atPath: workDir.appendingPathComponent("mytarget.ti2").path))