Compare commits

...
Author SHA1 Message Date
gronod c1c37bb7d7 test(m4): retry Start Read until the chartread session is running
macOS CI / package (pull_request) Canceled after 0s
macOS CI / build-and-test (pull_request) Canceled after 1m52s
macOS CI / build-and-test (push) Successful in 37m49s
macOS CI / package (push) Successful in 4m39s
testTwoPassAverageFailurePromotesFirstPass died on Gitea run 35443
waiting for btnCalibrate after a single Start click. Handheld in the
same job succeeded: AX reported enabled and synthesized the click, but
SwiftUI startRead() was still a no-op (same class as 35251).

Re-click until btnCancel/Calibrate/Trigger exist — Cancel is in the
tree for the whole session — then wait for Calibrate.
2026-09-14 18:40:27 +00:00
gronod d2466d9a66 Merge pull request 'test(m2): mock CUPS so Print All enables on GitHub macos-14' (!176) from fix/m2-print-all-mock-cups into develop
macOS CI / build-and-test (push) Failing after 37m56s
macOS CI / package (push) Skipped
Reviewed-on: #176
2026-09-14 17:35:39 +01:00
gronod 4af2d96294 test(m2): mock CUPS so Print All enables on GitHub macos-14
macOS CI / build-and-test (push) Skipped
macOS CI / build-and-test (pull_request) Canceled after 0s
macOS CI / package (pull_request) Canceled after 0s
testPrinttargFixtureGalleryAndStubbedPrint asserted btnPrintAll
immediately after the gallery appeared, without ICCERY_CUPS_BIN_DIR.
Gitea Monterey has system queues; GitHub macos-14-arm64 does not, so
selectedPrinter stays empty and the button stays disabled (run
34867767434). Point M2 at Fixtures/bin like M3, and wait for enable.
2026-09-14 16:32:57 +00:00
gronod d17aa962ce Merge pull request 'fix(ci): pin GitHub Actions to macos-14 and clamp the window on-screen' (#175) from fix/gh-ci-window-and-runner into develop
macOS CI / build-and-test (push) Canceled after 0s
macOS CI / package (push) Canceled after 0s
Reviewed-on: #175
2026-09-14 17:18:13 +01:00
gronod 93acd32b51 fix(ci): pin GitHub Actions to macos-14 and keep the window on-screen
macOS CI / build-and-test (push) Skipped
macOS CI / build-and-test (pull_request) Canceled after 0s
macOS CI / package (pull_request) Canceled after 0s
macos-latest is macos-26-arm64 (run 34864198118). A 1280x800 window
centered on that display hangs off the left edge, so XCTest sees
sidebar controls at x ≈ -116 and refuses the click. Pin the GitHub
workflow to macos-14 and clamp the main window to visibleFrame.
2026-09-14 16:17:20 +00:00
gronod 67cf452e59 Update .github/workflows/macos.yml
macOS CI / package (push) Canceled after 0s
macOS CI / build-and-test (push) Canceled after 27m49s
2026-09-14 16:44:50 +01:00
gronod 83ed53c7fc Merge pull request 'ci: GitHub Actions twin of the Gitea macOS workflow' (#174) from ci/github-workflows into develop
macOS CI / build-and-test (push) Successful in 40m30s
macOS CI / package (push) Successful in 3m27s
Reviewed-on: #174
2026-09-14 16:42:01 +01:00
4 changed files with 76 additions and 14 deletions
+5 -3
View File
@@ -1,7 +1,9 @@
# GitHub Actions twin of .gitea/workflows/macos.yml. # GitHub Actions twin of .gitea/workflows/macos.yml.
# Deltas from the Gitea file (everything else is the same jobs/steps): # Deltas from the Gitea file (everything else is the same jobs/steps):
# - runs-on macos-14: github.com retired macos-12 (the Gitea runner label). # - runs-on macos-14: github.com retired macos-12. Do not use
# The Gitea workflow already notes macos-14 works for this pipeline. # macos-latest — in 2026 that is macos-26-arm64, where a 1280×800
# window hangs off the virtual display and XCTest marks sidebar
# controls (x ≈ -116) as not hittable (run 34864198118).
# - actions/upload-artifact@v4: v3 is shut down on github.com. Gitea act_runner # - actions/upload-artifact@v4: v3 is shut down on github.com. Gitea act_runner
# still uses v3. # still uses v3.
# - No NODE_EXTRA_CA_CERTS / System keychain bundle: that is only for the # - No NODE_EXTRA_CA_CERTS / System keychain bundle: that is only for the
@@ -25,7 +27,7 @@ permissions:
jobs: jobs:
build-and-test: build-and-test:
runs-on: macos-26-intel runs-on: macos-14
env: env:
DERIVED: build/DerivedData-test DERIVED: build/DerivedData-test
steps: steps:
+33 -2
View File
@@ -56,10 +56,41 @@ final class AppDelegate: NSObject, NSApplicationDelegate {
} }
/// docs/21 §Shell: 1280×800 content, min 1100×700, centred. /// docs/21 §Shell: 1280×800 content, min 1100×700, centred.
/// GitHub-hosted Macs (and any display smaller than 1280×800) must
/// not get a window that hangs off-screen XCTest then reports
/// sidebar controls at negative x as not hittable (run 34864198118).
private func configureMainWindow(_ window: NSWindow) { private func configureMainWindow(_ window: NSWindow) {
window.setContentSize(NSSize(width: 1280, height: 800)) let desired = NSSize(width: 1280, height: 800)
window.contentMinSize = NSSize(width: 1100, height: 700) let minimum = NSSize(width: 1100, height: 700)
let visible = (window.screen ?? NSScreen.main)?.visibleFrame
?? NSRect(origin: .zero, size: desired)
window.contentMinSize = NSSize(
width: min(minimum.width, visible.width),
height: min(minimum.height, visible.height)
)
window.setContentSize(NSSize(
width: min(desired.width, visible.width),
height: min(desired.height, max(minimum.height, visible.height - 40))
))
window.center() window.center()
var frame = window.frame
if frame.width > visible.width {
frame.size.width = visible.width
}
if frame.height > visible.height {
frame.size.height = visible.height
}
frame.origin.x = min(
max(frame.origin.x, visible.minX),
visible.maxX - frame.width
)
frame.origin.y = min(
max(frame.origin.y, visible.minY),
visible.maxY - frame.height
)
window.setFrame(frame, display: true)
} }
/// Dock-click reopen: let the WindowGroup re-show or recreate the /// Dock-click reopen: let the WindowGroup re-show or recreate the
+6 -4
View File
@@ -36,6 +36,7 @@ final class Milestone2UITests: XCTestCase {
"ICCERY_UI_TESTING": "1", "ICCERY_UI_TESTING": "1",
"ICCERY_TEST_ROOT": testRoot.path, "ICCERY_TEST_ROOT": testRoot.path,
"ICCERY_ARGYLL_BINARY_DIR": binDir.path, "ICCERY_ARGYLL_BINARY_DIR": binDir.path,
"ICCERY_CUPS_BIN_DIR": binDir.path,
"ICCERY_TEST_SAVE_TARGET": "ICCERY_TEST_SAVE_TARGET":
workDir.appendingPathComponent("mytarget.ti1").path, workDir.appendingPathComponent("mytarget.ti1").path,
"ICCERY_TEST_WORKDIR": workDir.path, "ICCERY_TEST_WORKDIR": workDir.path,
@@ -218,11 +219,12 @@ final class Milestone2UITests: XCTestCase {
XCTAssertTrue(FileManager.default.fileExists( XCTAssertTrue(FileManager.default.fileExists(
atPath: workDir.appendingPathComponent("mytarget.ti2").path)) atPath: workDir.appendingPathComponent("mytarget.ti2").path))
// Print panel is live from M3; a default printer is selected // Print panel is live from M3. GitHub macos-14 has no system
// so both the all-pages and per-page print buttons are enabled. // queues, so mock CUPS (`ICCERY_CUPS_BIN_DIR`) must enumerate
// before Print All / per-page enable (run 34867767434).
XCTAssertTrue(element("rawPrintPanel").exists) XCTAssertTrue(element("rawPrintPanel").exists)
XCTAssertTrue(app.buttons["btnPrintAll"].isEnabled) _ = waitUntilEnabled("btnPrintAll", timeout: 15)
XCTAssertTrue(app.buttons["btnPrintPage-0"].isEnabled) _ = waitUntilEnabled("btnPrintPage-0", timeout: 15)
XCTAssertTrue(app.buttons["btnAdvanceToStage3"].isEnabled) XCTAssertTrue(app.buttons["btnAdvanceToStage3"].isEnabled)
} }
+32 -5
View File
@@ -154,15 +154,34 @@ final class Milestone4UITests: XCTestCase {
/// Runs the mock handheld chartread session to completion /// Runs the mock handheld chartread session to completion
/// (start calibrate strip A strip B Done & Save). /// (start calibrate strip A strip B Done & Save).
///
/// `isEnabled` can be true in AX while the SwiftUI action is still
/// a no-op (runs 35251, 35443). Re-click until the session is
/// actually running (`btnCancel` is shown whenever
/// `isChartreadRunning`), then wait for Calibrate.
private func driveOnePass(startButton: String) { private func driveOnePass(startButton: String) {
let start = app.buttons[startButton] let start = app.buttons[startButton]
XCTAssertTrue(start.waitForExistence(timeout: 10)) XCTAssertTrue(start.waitForExistence(timeout: 10), startButton)
let deadline = Date().addingTimeInterval(10) let enabledBy = Date().addingTimeInterval(10)
while Date() < deadline, !start.isEnabled { while Date() < enabledBy, !start.isEnabled {
RunLoop.current.run(until: Date().addingTimeInterval(0.1)) RunLoop.current.run(until: Date().addingTimeInterval(0.1))
} }
XCTAssertTrue(start.isEnabled) XCTAssertTrue(start.isEnabled, "\(startButton) never enabled")
start.click()
let sessionBy = Date().addingTimeInterval(25)
while Date() < sessionBy, !chartreadSessionRunning {
if start.exists, start.isEnabled {
start.click()
}
RunLoop.current.run(until: Date().addingTimeInterval(0.4))
}
XCTAssertTrue(
chartreadSessionRunning,
"\(startButton) click never started chartread; "
+ "notice=\(element("noticeText").value as? String ?? "") "
+ "start.exists=\(start.exists)"
)
_ = waitFor("btnCalibrate", timeout: 25) _ = waitFor("btnCalibrate", timeout: 25)
app.buttons["btnCalibrate"].click() app.buttons["btnCalibrate"].click()
driveStripsUntilDone() driveStripsUntilDone()
@@ -170,6 +189,14 @@ final class Milestone4UITests: XCTestCase {
app.buttons["btnDoneRead"].firstMatch.click() app.buttons["btnDoneRead"].firstMatch.click()
} }
/// `btnCancel` is in the tree for the whole chartread session;
/// Calibrate/Trigger only appear after the first classified prompt.
private var chartreadSessionRunning: Bool {
element("btnCancel").exists
|| element("btnCalibrate").exists
|| element("btnTrigger").exists
}
/// Clicks Trigger for each remaining strip until `btnDoneRead` /// Clicks Trigger for each remaining strip until `btnDoneRead`
/// appears the button is re-polled each pass so a click that /// appears the button is re-polled each pass so a click that
/// races a state transition isn't lost. /// races a state transition isn't lost.