From 97ac2268f908dbd9093b2271a7763087d0425136 Mon Sep 17 00:00:00 2001 From: Robin | Liquidium Date: Sat, 12 Sep 2026 08:50:15 +0700 Subject: [PATCH] Speed up menu bar UI test clicks --- README.md | 4 +++ UITests/DaylineUITests/DaylineUITests.swift | 37 +++++++++++++++++++-- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d0c2d2f..9033107 100644 --- a/README.md +++ b/README.md @@ -333,6 +333,10 @@ the complete runner log, privacy-safe app breadcrumbs, and always-kept visual and element-state checkpoints for successful as well as failed tests. The checkpoint PNGs and text files are also extracted into a directly browsable `checkpoints/` directory. +Menu-bar clicks use a scoped, private XCTest event-confirmation timeout to avoid +its five-second wait for a missing mouse-up acknowledgement. The normal timeout +is restored after each toggle, and app-idle and panel-readiness checks remain +enabled. The helper fails explicitly if an Xcode update removes the required API. The same suite runs on a GitHub-hosted macOS runner for every pull request and push to `main`, so it does not use the local mouse or interrupt local work. diff --git a/UITests/DaylineUITests/DaylineUITests.swift b/UITests/DaylineUITests/DaylineUITests.swift index 8844fb6..e8e8104 100644 --- a/UITests/DaylineUITests/DaylineUITests.swift +++ b/UITests/DaylineUITests/DaylineUITests.swift @@ -521,7 +521,7 @@ final class DaylineUITests: XCTestCase { if statusMenuIndicator.exists { let statusItem = app.descendants(matching: .statusItem)["dayline.menuBarItem"].firstMatch XCTAssertTrue(statusItem.waitForExistenceIfNeeded(timeout: 3)) - statusItem.click() + try clickMenuBarItem(statusItem) waitForRemoval(statusMenuIndicator) } app.activate() @@ -890,10 +890,43 @@ final class DaylineUITests: XCTestCase { return } - statusItem.click() + try clickMenuBarItem(statusItem) XCTAssertTrue(element("dayline.refresh").waitForExistenceIfNeeded(timeout: 5)) } + private func clickMenuBarItem(_ statusItem: XCUIElement) throws { + // MenuBarExtra clicks don't acknowledge XCTest's mouse-up event, so its default + // confirmation timeout adds five seconds even after the panel is ready. This + // private XCTest setting changes only that timeout; idle/readiness checks remain. + let sessionClass = try XCTUnwrap( + NSClassFromString("XCTRunnerDaemonSession") as? NSObject.Type, + "This Xcode version no longer exposes the UI automation session" + ) + let sharedSession = NSSelectorFromString("sharedSession") + guard sessionClass.responds(to: sharedSession) else { + XCTFail("This Xcode version no longer exposes the shared UI automation session") + return + } + let session = try XCTUnwrap( + sessionClass.perform(sharedSession)?.takeUnretainedValue() as? NSObject + ) + let key = "implicitEventConfirmationIntervalForCurrentContext" + let overrideKey = "implicitEventConfirmationIntervalForCurrentContextWithoutSideEffects" + guard session.responds(to: NSSelectorFromString(key)), + session.responds(to: NSSelectorFromString("setImplicitEventConfirmationIntervalForCurrentContextWithoutSideEffects:")) else { + XCTFail("This Xcode version no longer supports the scoped menu click confirmation timeout") + return + } + let previousInterval = try XCTUnwrap(session.value(forKey: key) as? NSNumber) + // The ordinary setter restores only at test teardown, not at activity end. + // Restore explicitly so subsequent clicks retain XCTest's normal confirmation. + defer { session.setValue(previousInterval, forKey: overrideKey) } + XCTContext.runActivity(named: "Toggle menu bar panel") { _ in + session.setValue(0.1, forKey: overrideKey) + statusItem.click() + } + } + private func element(_ identifier: String) -> XCUIElement { app.descendants(matching: .any)[identifier].firstMatch }