From 8d0db95ed8db47ae22589a7d83e2bea1ccf425fc Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Mon, 19 Oct 2026 22:10:28 +0000 Subject: [PATCH] fix(ci): align macOS and web parity capture geometry Co-authored-by: Tyler Dane --- .../CompassData/UITestLaunchPolicy.swift | 6 +++++ .../Layout/ParityCaptureGeometry.swift | 24 +++++++++++++++++++ .../ParityCaptureGeometryTests.swift | 10 ++++++++ .../NativeParityCaptureTests.swift | 24 ++++++++++++++++++- e2e/parity/seed-demo-fixture.util.ts | 11 +++++++++ 5 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 apps/calendar-macos/CompassKit/Sources/CompassKit/Layout/ParityCaptureGeometry.swift create mode 100644 apps/calendar-macos/CompassKitTests/ParityCaptureGeometryTests.swift diff --git a/apps/calendar-macos/CompassData/Sources/CompassData/UITestLaunchPolicy.swift b/apps/calendar-macos/CompassData/Sources/CompassData/UITestLaunchPolicy.swift index e9f2a034b..115d8ac87 100644 --- a/apps/calendar-macos/CompassData/Sources/CompassData/UITestLaunchPolicy.swift +++ b/apps/calendar-macos/CompassData/Sources/CompassData/UITestLaunchPolicy.swift @@ -1,3 +1,4 @@ +import CompassKit import Foundation /// Launch arguments read by native UI for XCUITest only. Production launches omit these. @@ -66,6 +67,11 @@ public enum UITestLaunchPolicy { /// Full week column count so demo fixture events stay in the focus layout during XCUITest. public static var pinnedWeekGridTrackWidth: CGFloat? { + if ProcessInfo.processInfo.environment["PARITY_CAPTURE"] == "1" + || ProcessInfo.processInfo.arguments.contains("-COMPASS_UI_TEST_PARITY_CAPTURE") + { + return CGFloat(ParityCaptureGeometry.contentTrackWidth) + } if initialGridFocusEventId != nil || openFocusedEventFormAfterInitialGridFocus || ProcessInfo.processInfo.arguments.contains("-COMPASS_UI_TEST_PIN_WEEK_GRID_TRACK") diff --git a/apps/calendar-macos/CompassKit/Sources/CompassKit/Layout/ParityCaptureGeometry.swift b/apps/calendar-macos/CompassKit/Sources/CompassKit/Layout/ParityCaptureGeometry.swift new file mode 100644 index 000000000..1b8253ae7 --- /dev/null +++ b/apps/calendar-macos/CompassKit/Sources/CompassKit/Layout/ParityCaptureGeometry.swift @@ -0,0 +1,24 @@ +import Foundation + +/// Geometry for desktop ↔ web parity screenshots. Keep in sync with +/// `e2e/parity/seed-demo-fixture.util.ts` and `apps/calendar-web/src/index.html` +/// boot track math (1280×820, sidebar open @ 345px, content pl-8). +public enum ParityCaptureGeometry { + public static let viewportWidth: Double = 1280 + public static let contentLeadingInset: Double = 32 + public static let sidebarDividerWidth: Double = 32 + public static let defaultSidebarWidth: Double = 345 + public static let gridMarginLeft: Double = Double(GridMetrics.gridMarginLeft) + + /// Width of the week grid track (excluding sidebar chrome). + public static var contentTrackWidth: Double { + viewportWidth - contentLeadingInset - (sidebarDividerWidth + defaultSidebarWidth) + } + + public static var visibleDayCount: Int { + CalendarWindowMath.computeVisibleDayCount( + trackWidth: contentTrackWidth, + marginLeft: gridMarginLeft + ) + } +} diff --git a/apps/calendar-macos/CompassKitTests/ParityCaptureGeometryTests.swift b/apps/calendar-macos/CompassKitTests/ParityCaptureGeometryTests.swift new file mode 100644 index 000000000..36f67e497 --- /dev/null +++ b/apps/calendar-macos/CompassKitTests/ParityCaptureGeometryTests.swift @@ -0,0 +1,10 @@ +import CompassKit +import XCTest + +final class ParityCaptureGeometryTests: XCTestCase { + func testContentTrackWidthMatchesWebBootShell() { + // index.html: track = innerWidth - 32 - (32 + sidebarWidth) + XCTAssertEqual(ParityCaptureGeometry.contentTrackWidth, 871, accuracy: 0.1) + XCTAssertEqual(ParityCaptureGeometry.visibleDayCount, 5) + } +} diff --git a/apps/calendar-macos/CompassUITests/NativeParityCaptureTests.swift b/apps/calendar-macos/CompassUITests/NativeParityCaptureTests.swift index ece6823c3..d3b892e60 100644 --- a/apps/calendar-macos/CompassUITests/NativeParityCaptureTests.swift +++ b/apps/calendar-macos/CompassUITests/NativeParityCaptureTests.swift @@ -5,7 +5,12 @@ import XCTest /// `.github/workflows/desktop-web-parity-screenshots.yml`). Run with /// `PARITY_CAPTURE=1` and `PARITY_OUTPUT_DIR` set; skips ReferenceImages diff. final class NativeParityCaptureTests: XCTestCase { - private static let demoLaunchArgs = ["-COMPASS_FIXTURE", "demo", "-compass.theme", "light-beach"] + private static let demoLaunchArgs = [ + "-COMPASS_FIXTURE", "demo", + "-compass.theme", "light-beach", + "-COMPASS_UI_TEST_PARITY_CAPTURE", + "-\(OnboardingStorageKeys.hasSeenWelcome)", "true", + ] @MainActor func testExportParitySurfaces() throws { @@ -24,12 +29,14 @@ final class NativeParityCaptureTests: XCTestCase { @MainActor private func captureWeekGrid() { let window = launchDemoWindow() + prepareParityGrid(window) NativeImageSnapshotSupport.captureWindow(window, named: "week-grid") } @MainActor private func captureMiniCalendar() { let window = launchDemoWindow() + prepareParityGrid(window) XCTAssertTrue( window.descendants(matching: .any)["compass-native-month-picker"].waitForExistence(timeout: 10)) window.typeKey("i", modifierFlags: []) @@ -39,6 +46,7 @@ final class NativeParityCaptureTests: XCTestCase { @MainActor private func captureEventForm() { let window = launchDemoWindow() + prepareParityGrid(window) window.typeKey("c", modifierFlags: []) XCTAssertTrue( window.descendants(matching: .any)["compass-event-form"].waitForExistence(timeout: 8)) @@ -48,6 +56,7 @@ final class NativeParityCaptureTests: XCTestCase { @MainActor private func captureCommandPalette() { let window = launchDemoWindow() + prepareParityGrid(window) window.typeKey("k", modifierFlags: [.command]) XCTAssertTrue( window.descendants(matching: .any)["compass-native-command-palette"].waitForExistence(timeout: 8)) @@ -57,6 +66,7 @@ final class NativeParityCaptureTests: XCTestCase { @MainActor private func captureSettings() { let window = launchDemoWindow() + prepareParityGrid(window) window.typeKey(",", modifierFlags: [.command]) XCTAssertTrue( window.descendants(matching: .any)["compass-native-settings"].waitForExistence(timeout: 8)) @@ -84,4 +94,16 @@ final class NativeParityCaptureTests: XCTestCase { XCTAssertTrue(window.waitForExistence(timeout: 15)) return window } + + /// Dismiss demo chrome and wait for the shared demo-seed grid event (web parity uses the same fixture). + @MainActor + private func prepareParityGrid(_ window: XCUIElement) { + let okay = window.buttons["Okay"] + if okay.waitForExistence(timeout: 4) { + okay.tap() + } + XCTAssertTrue( + window.buttons["Morning standup"].waitForExistence(timeout: 20), + "Expected demo-seed timed event on the week grid") + } } diff --git a/e2e/parity/seed-demo-fixture.util.ts b/e2e/parity/seed-demo-fixture.util.ts index 82d7b8611..b08e24ef0 100644 --- a/e2e/parity/seed-demo-fixture.util.ts +++ b/e2e/parity/seed-demo-fixture.util.ts @@ -5,6 +5,15 @@ import { join } from "node:path"; /** Matches `AppDelegate` default content size on macOS. */ export const PARITY_VIEWPORT = { width: 1280, height: 820 } as const; +/** Keep in sync with `ParityCaptureGeometry.swift` and index.html boot track math. */ +export const PARITY_SIDEBAR_WIDTH = 345; +export const PARITY_CONTENT_LEADING_INSET = 32; +export const PARITY_SIDEBAR_DIVIDER_WIDTH = 32; +export const PARITY_CONTENT_TRACK_WIDTH = + PARITY_VIEWPORT.width - + PARITY_CONTENT_LEADING_INSET - + (PARITY_SIDEBAR_DIVIDER_WIDTH + PARITY_SIDEBAR_WIDTH); + const DEMO_SEED_PATH = join( process.cwd(), "apps/calendar-macos/CompassKit/Sources/CompassKit/Resources/Fixtures/demo-seed.json", @@ -34,6 +43,8 @@ export async function installParityWebEnvironment( "compass.theme": "light-beach", "compass.migration.demo-data-seed-v2": "done", "compass.localCalendarId": demoFixture.calendarId, + "compass.view.sidebar-open": "true", + "compass.sidebar.width": String(PARITY_SIDEBAR_WIDTH), }; if (dismissOnboarding) { localStorageSeed["compass.onboarding.has-seen-welcome"] = "true";