From 5d42363f902f34d41b36dc5b6fd00f17efcba748 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 22 Oct 2026 03:08:48 +0000 Subject: [PATCH 1/3] fix(macos): name welcome buttons by their title, not title plus keycap The welcome modal's buttons pair a title with a keycap chip and had no explicit label, so accessibility read "Get started for free, Enter". The onboarding parity capture added in #4707 clicks buttons["Get started for free"] and fails on every run since. Label each welcome button with its title; the keycap is a visual hint. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01GKHjv2HDx1DFAnG4cfSxcr --- .../Sources/CompassUI/Onboarding/WelcomeModalView.swift | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/apps/calendar-macos/CompassUI/Sources/CompassUI/Onboarding/WelcomeModalView.swift b/apps/calendar-macos/CompassUI/Sources/CompassUI/Onboarding/WelcomeModalView.swift index c8321b888..dff2f371e 100644 --- a/apps/calendar-macos/CompassUI/Sources/CompassUI/Onboarding/WelcomeModalView.swift +++ b/apps/calendar-macos/CompassUI/Sources/CompassUI/Onboarding/WelcomeModalView.swift @@ -179,6 +179,8 @@ struct WelcomeModalView: View { .shadow(color: .black.opacity(0.15), radius: 6, y: 3) } .buttonStyle(.plain) + // The keycap is a visual hint; the title alone names the button. + .accessibilityLabel(title) } private func secondaryButton(title: String, hint: String, action: @escaping () -> Void) -> some View { @@ -195,6 +197,8 @@ struct WelcomeModalView: View { .overlay(Capsule().stroke(theme.borderColor, lineWidth: 1)) } .buttonStyle(.plain) + // The keycap is a visual hint; the title alone names the button. + .accessibilityLabel(title) } private func quietTextButton(title: String, hint: String, action: @escaping () -> Void) -> some View { @@ -208,6 +212,8 @@ struct WelcomeModalView: View { .frame(maxWidth: .infinity, minHeight: 32) } .buttonStyle(.plain) + // The keycap is a visual hint; the title alone names the button. + .accessibilityLabel(title) } private func pillButton(title: String, hint: String, action: @escaping () -> Void) -> some View { @@ -225,5 +231,7 @@ struct WelcomeModalView: View { .overlay(Capsule().stroke(theme.borderColor, lineWidth: 1)) } .buttonStyle(.plain) + // The keycap is a visual hint; the title alone names the button. + .accessibilityLabel(title) } } From 77e87f4e309cfb77c501973831d1afc29f33c405 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 22 Oct 2026 03:18:26 +0000 Subject: [PATCH 2/3] test(macos): scope the welcome capture's button clicks to the welcome panel With the welcome buttons named by title, buttons["Next"] also matched the grid's week "Next" button behind the modal, so the click failed with multiple matches. Query the buttons inside compass-native-welcome-modal. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01GKHjv2HDx1DFAnG4cfSxcr --- .../CompassUITests/NativeParityCaptureTests.swift | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/apps/calendar-macos/CompassUITests/NativeParityCaptureTests.swift b/apps/calendar-macos/CompassUITests/NativeParityCaptureTests.swift index f7b966880..0abc77cb0 100644 --- a/apps/calendar-macos/CompassUITests/NativeParityCaptureTests.swift +++ b/apps/calendar-macos/CompassUITests/NativeParityCaptureTests.swift @@ -260,14 +260,16 @@ final class NativeParityCaptureTests: XCTestCase { app.launch() let window = app.windows["Compass"] XCTAssertTrue(window.waitForExistence(timeout: 15)) - XCTAssertTrue( - window.descendants(matching: .any)["compass-native-welcome-modal"].waitForExistence(timeout: 15)) + let welcome = window.descendants(matching: .any)["compass-native-welcome-modal"] + XCTAssertTrue(welcome.waitForExistence(timeout: 15)) sleep(1) NativeImageSnapshotSupport.captureWindow(window, named: "onboarding-welcome") - window.buttons["Get started for free"].click() - window.buttons["Next"].click() + // Scope to the panel: the grid's own "Next" (week) button is still in + // the window's accessibility tree behind the modal. + welcome.buttons["Get started for free"].click() + welcome.buttons["Next"].click() XCTAssertTrue( - window.buttons["Start free trial with Google"].waitForExistence(timeout: 8)) + welcome.buttons["Start free trial with Google"].waitForExistence(timeout: 8)) sleep(1) NativeImageSnapshotSupport.captureWindow(window, named: "onboarding-welcome-account-choice") } From b031ea7615b6c8a37b21f6900fd31c7c1c164767 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 22 Oct 2026 03:54:23 +0000 Subject: [PATCH 3/3] test(macos): wait for the local-only choice on the welcome account step Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01GKHjv2HDx1DFAnG4cfSxcr --- .../CompassUITests/NativeParityCaptureTests.swift | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/calendar-macos/CompassUITests/NativeParityCaptureTests.swift b/apps/calendar-macos/CompassUITests/NativeParityCaptureTests.swift index 0abc77cb0..0a04d4129 100644 --- a/apps/calendar-macos/CompassUITests/NativeParityCaptureTests.swift +++ b/apps/calendar-macos/CompassUITests/NativeParityCaptureTests.swift @@ -268,8 +268,9 @@ final class NativeParityCaptureTests: XCTestCase { // the window's accessibility tree behind the modal. welcome.buttons["Get started for free"].click() welcome.buttons["Next"].click() - XCTAssertTrue( - welcome.buttons["Start free trial with Google"].waitForExistence(timeout: 8)) + // The provider buttons depend on the backend config; the local-only + // choice is always on the account step. + XCTAssertTrue(welcome.buttons["On this device only"].waitForExistence(timeout: 8)) sleep(1) NativeImageSnapshotSupport.captureWindow(window, named: "onboarding-welcome-account-choice") }