From 5da581d4ca35ea80d2845d0b4b0ad54e19b81bef Mon Sep 17 00:00:00 2001 From: Nabzx Date: Sat, 26 Sep 2026 18:58:04 +0100 Subject: [PATCH 1/2] CI: actually run the Swift test suites (#440) hotkey-helper and accessibility-helper both have real test targets, wired into their Package.swift - nothing ever invoked them. Same shape as #425: a native-side regression could merge on a green check because the check never looked. transcription-helper has no test target (needs FluidAudio mocked out first) and isn't built in CI either - that gap stays open, called out in the new comment rather than silently left for someone to rediscover. Claude-Session: https://claude.ai/code/session_0144sxo5CJiyk99vaR7sgjuj --- .github/workflows/build.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3851681..4f061e8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -35,3 +35,11 @@ jobs: # suite. A PR could break dictationCoordinator.test.js and still # merge on a green check, because the check never looked. - run: npm test + # #440: hotkey-helper and accessibility-helper both have real Swift + # test suites, wired as .testTarget in their Package.swift, that no + # CI workflow or npm script ever invoked - a native-side regression + # could merge on a green check the same way #425's electron tests + # could. transcription-helper has no test target yet (needs FluidAudio + # mocked out first) and isn't built here either - still open. + - run: swift test --package-path native/hotkey-helper + - run: swift test --package-path native/accessibility-helper From d263d4c5c6c89277d71c20cd1b808597f054044d Mon Sep 17 00:00:00 2001 From: Nabzx Date: Sat, 26 Sep 2026 19:05:51 +0100 Subject: [PATCH 2/2] Fix two rung-1 fakes that never actually verified the readback (#440) The first CI run of accessibility-helper's suite - ever, since #440's CI step is what runs it for the first time - failed two tests neither this session nor anyone else had actually seen fail: retriesFocus- ResolutionWhenTheAXTreeWasBrieflyNotReady and settleGuardPassesOnce- TheTargetStabilizes. Both built a FakeAccessibilityTarget without valueToReadBack, which defaults to nil. InjectionEngine's rung 1 confirms a write by reading the field back (`let after = focused.readValue(), after.contains(text)`) - against a fake with nothing to read back, that binding always fails, so both tests silently fell through to rung 2 and asserted an outcome ("wrote into the field") the fake could never produce. Not a production regression - InjectionEngine.swift is unchanged - just a test fixture missing the one line every other rung-1 test already has. Claude-Session: https://claude.ai/code/session_0144sxo5CJiyk99vaR7sgjuj --- .../AccessibilityInjectionTests/InjectionEngineTests.swift | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/native/accessibility-helper/Tests/AccessibilityInjectionTests/InjectionEngineTests.swift b/native/accessibility-helper/Tests/AccessibilityInjectionTests/InjectionEngineTests.swift index edd2be3..8eb1ef2 100644 --- a/native/accessibility-helper/Tests/AccessibilityInjectionTests/InjectionEngineTests.swift +++ b/native/accessibility-helper/Tests/AccessibilityInjectionTests/InjectionEngineTests.swift @@ -295,7 +295,8 @@ struct InjectionEngineTests { // first read misses, but the tree comes good a beat later. Before // #227 this dropped straight to blind-paste-or-hold. let target = FakeAccessibilityTarget( - fieldInfo: FieldInfo(role: "AXTextField", valueChars: 10, selectedTextSettable: true) + fieldInfo: FieldInfo(role: "AXTextField", valueChars: 10, selectedTextSettable: true), + valueToReadBack: "hello" ) let (engine, time, paster, _) = makeEngine(focusTarget: target, missesBeforeSuccess: 2) @@ -379,7 +380,8 @@ struct InjectionEngineTests { @Test func settleGuardPassesOnceTheTargetStabilizes() { let time = SimulatedTime() let target = FakeAccessibilityTarget( - fieldInfo: FieldInfo(role: "AXTextField", valueChars: 5, selectedTextSettable: true) + fieldInfo: FieldInfo(role: "AXTextField", valueChars: 5, selectedTextSettable: true), + valueToReadBack: "hello" ) let paster = FakePaster(result: PasteResult(delivered: true, verified: false, note: "")) let typer = FakeTyper()