From f5c57649e1f5428cb9b1fbaae7985ccd555f0e3d Mon Sep 17 00:00:00 2001 From: Gronod Date: Sun, 13 Sep 2026 15:52:53 +0100 Subject: [PATCH] test(m10): combine gamut layer toggle AX; harden gallery wait on macOS 12 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Run 33803 still reported the layer toggles disabled after a real waitUntilEnabled: on macOS 12 the identifier lands on the Toggle's container element, which never reports isEnabled — combine the Toggle's children so the a11y leaf is the checkbox itself (checkbox style unchanged). testPrinttargFixtureGalleryAndStubbedPrint flaked once on the same runner: wait for btnCreateLayout enabled before clicking and retry once when the gallery never materialises. Refs #147 #149 #146 Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- Sources/ICCery/GamutView.swift | 4 +++ Tests/ICCeryUITests/Milestone2UITests.swift | 36 +++++++++++++++++++-- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/Sources/ICCery/GamutView.swift b/Sources/ICCery/GamutView.swift index 7ede277..500dadc 100644 --- a/Sources/ICCery/GamutView.swift +++ b/Sources/ICCery/GamutView.swift @@ -144,6 +144,10 @@ struct GamutView: View { .toggleStyle(.checkbox) .disabled(layer == nil || viewModel.viewerUnavailable) .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)") } diff --git a/Tests/ICCeryUITests/Milestone2UITests.swift b/Tests/ICCeryUITests/Milestone2UITests.swift index 4455f0a..0e45344 100644 --- a/Tests/ICCeryUITests/Milestone2UITests.swift +++ b/Tests/ICCeryUITests/Milestone2UITests.swift @@ -85,6 +85,31 @@ final class Milestone2UITests: XCTestCase { 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 /// `waitForExistence`, which always burns its full timeout on the /// negative path. @@ -181,8 +206,15 @@ final class Milestone2UITests: XCTestCase { XCTAssertTrue(element("tiffDpi").exists) XCTAssertTrue(element("targetLabelPreview").exists) - app.buttons["btnCreateLayout"].click() - XCTAssertTrue(waitFor("galleryPage-0", timeout: 20).exists) + // On the slow macOS 12 runner a synthesized click can land + // 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( atPath: workDir.appendingPathComponent("mytarget.ti2").path)) -- 2.39.5