Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,6 @@ import CompassKit
import Foundation

extension NativeCalendarRootModel {
/// Web `VIEW_SHORTCUT_KEYS`: view switches use keyup globally; grid jump uses
/// keydown. These letters fall through jump mode so `nav-*-view` can run.
private static let viewNavigationFallthroughLetters: Set<Character> = ["d", "w", "l"]

public var eventJumpSelection: EventJumpSelectionStore { overlayStores.eventJumpSelection }

public var eventJumpStatusText: String? {
Expand Down Expand Up @@ -98,7 +94,7 @@ extension NativeCalendarRootModel {
public func handleEventJumpKeystroke(_ key: Character) -> Bool {
guard eventJumpSelection.modeActive else { return false }
let normalized = Character(String(key).lowercased())
if Self.viewNavigationFallthroughLetters.contains(normalized) {
if DayJumpPrefixes.viewNavigationFallthroughLetters.contains(normalized) {
return false
}
if normalized.isNumber {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,18 @@ final class NativeCalendarRootModelEventJumpTests: XCTestCase {
XCTAssertFalse(model.handleEventJumpKeystroke("l"))
}

func testViewNavigationFallthroughMatchesShiftDecoratedDayPrefixes() {
for letter in DayJumpPrefixes.viewNavigationFallthroughLetters {
let lowercase = String(letter).lowercased()
let isShiftDecorated = DayJumpPrefixes.shiftDecoratedJumpPrefixes.contains(lowercase)
let matchesSingleLetterDay = DayJumpPrefixes.dayPrefix(forShiftedLetter: letter) == lowercase
XCTAssertEqual(
isShiftDecorated,
matchesSingleLetterDay,
"Fallthrough letter \(letter) drifted vs shift-decorated jump hints")
}
}

func testJumpModeLeavesViewSwitchLettersForGridRouter() async throws {
let fixture = try DemoSeedFixture.load()
let environment = try NativeCalendarEnvironment(inMemoryDatabase: true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,23 @@ import Foundation

/// Weekday day-jump letter prefixes. Mirrors web `DAY_JUMP_PREFIX_BY_WEEKDAY`.
public enum DayJumpPrefixes {
/// Day prefixes whose bare letter is a macOS view shortcut during event jump
/// (`w` → week view). Column and chip labels show Shift for those keys; the
/// web grid still shows the bare letter because view shortcuts use keyup.
public static let shiftDecoratedJumpPrefixes: Set<String> = ["w"]
/// Web `VIEW_SHORTCUT_KEYS` letters that fall through jump keydown on macOS
/// (`NativeCalendarRootModel.handleEventJumpKeystroke`) so grid routing can
/// run `nav-*-view`. Keep in sync with shift-decorated jump chip labels.
public static let viewNavigationFallthroughLetters: Set<Character> = ["d", "w", "l"]

/// Day prefixes whose bare letter is a view-navigation fallthrough during
/// event jump (`w` → week view). Column and chip labels show Shift for those
/// keys; the web grid still shows the bare letter because view shortcuts use keyup.
public static var shiftDecoratedJumpPrefixes: Set<String> {
Set(
viewNavigationFallthroughLetters.compactMap { letter in
guard let prefix = dayPrefix(forShiftedLetter: letter),
prefix == String(letter).lowercased()
else { return nil }
return prefix
})
}

public static func prefix(forWeekday sundayBased: Int) -> String {
switch sundayBased {
Expand Down
12 changes: 12 additions & 0 deletions apps/calendar-macos/CompassKitTests/DayJumpPrefixesTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,16 @@ final class DayJumpPrefixesTests: XCTestCase {
XCTAssertEqual(DayJumpPrefixes.eventJumpChipLabel(hint: "w1"), "⇧w1")
XCTAssertEqual(DayJumpPrefixes.eventJumpChipLabel(hint: "w10"), "⇧w10")
}

func testShiftDecoratedPrefixesTrackViewNavigationFallthrough() {
XCTAssertEqual(DayJumpPrefixes.shiftDecoratedJumpPrefixes, Set(["w"]))
for letter in DayJumpPrefixes.viewNavigationFallthroughLetters {
let lowercase = String(letter).lowercased()
if let dayPrefix = DayJumpPrefixes.dayPrefix(forShiftedLetter: letter), dayPrefix == lowercase {
XCTAssertTrue(
DayJumpPrefixes.shiftDecoratedJumpPrefixes.contains(lowercase),
"Expected \(lowercase) in shift-decorated set")
}
}
}
}
86 changes: 86 additions & 0 deletions apps/calendar-macos/CompassUITests/EventJumpDayPrefixUITests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,90 @@ final class EventJumpDayPrefixUITests: XCTestCase {
evidence.lifetime = .keepAlways
add(evidence)
}

/// Demo `referenceNow` (2026-06-10) is a Wednesday; timed events that day are
/// hinted `w1` (standup), `w2`, `w3` (Exercise) in stable start-time order.
@MainActor
func testShiftWednesdayEventJumpChipW1FocusesStandup() {
let app = XCUIApplication.compassUITest()
app.launchArguments += [
"-COMPASS_FIXTURE", "demo",
"-COMPASS_UI_TEST_PIN_WEEK_GRID_TRACK",
"-COMPASS_UI_TEST_ACTIVATE_EVENT_JUMP",
]
app.launch()
let window = app.windows["Compass"]
XCTAssertTrue(window.waitForExistence(timeout: 15))
let wednesdayColumn = window.descendants(matching: .any)["compass-grid-column-2026-06-10"]
XCTAssertTrue(
wednesdayColumn.waitForExistence(timeout: 15),
"Expected pinned demo week to include Wednesday 2026-06-10")
XCTAssertTrue(
window.staticTexts["Morning standup"].waitForExistence(timeout: 10),
"Expected Wednesday Morning standup on demo grid")
window.click()
let w1Chip = window.staticTexts.matching(
NSPredicate(format: "identifier == %@ AND label == %@", "compass-event-jump-chip", "⇧w1")
).firstMatch
XCTAssertTrue(
w1Chip.waitForExistence(timeout: 15),
"Expected ⇧w1 chip for first Wednesday timed event")
typeEventJumpChipLabel("⇧w1", in: window)
let probe = window.descendants(matching: .any)["compass-grid-event-focused"]
XCTAssertTrue(probe.waitForExistence(timeout: 8))
XCTAssertTrue(
window.buttons["Morning standup"].waitForExistence(timeout: 4),
"Expected Shift+W1 jump to focus Morning standup")
}

@MainActor
func testShiftWSelectsWednesdayWhileJumpModeActive() {
let app = XCUIApplication.compassUITest()
app.launchArguments += [
"-COMPASS_FIXTURE", "demo",
"-COMPASS_UI_TEST_PIN_WEEK_GRID_TRACK",
"-COMPASS_UI_TEST_ACTIVATE_EVENT_JUMP",
]
app.launch()
let window = app.windows["Compass"]
XCTAssertTrue(window.waitForExistence(timeout: 15))
XCTAssertTrue(
window.descendants(matching: .any)["compass-grid-column-2026-06-10"].waitForExistence(timeout: 15))
window.click()
window.typeKey("w", modifierFlags: .shift)
let status = window.descendants(matching: .any)["compass-native-event-jump-status"]
XCTAssertTrue(status.waitForExistence(timeout: 6))
let statusText = (status.value as? String) ?? status.label
XCTAssertTrue(
statusText.localizedCaseInsensitiveContains("Wednesday"),
"Expected Shift+W to select Wednesday, got: \(statusText)")
}

@MainActor
func testShiftWednesdayEventJumpChipW3FocusesExercise() {
let app = XCUIApplication.compassUITest()
app.launchArguments += [
"-COMPASS_FIXTURE", "demo",
"-COMPASS_UI_TEST_PIN_WEEK_GRID_TRACK",
"-COMPASS_UI_TEST_ACTIVATE_EVENT_JUMP",
]
app.launch()
let window = app.windows["Compass"]
XCTAssertTrue(window.waitForExistence(timeout: 15))
XCTAssertTrue(
window.descendants(matching: .any)["compass-grid-column-2026-06-10"].waitForExistence(timeout: 15))
XCTAssertTrue(window.buttons["Exercise"].waitForExistence(timeout: 10))
window.click()
let w3Chip = window.staticTexts.matching(
NSPredicate(format: "identifier == %@ AND label == %@", "compass-event-jump-chip", "⇧w3")
).firstMatch
XCTAssertTrue(
w3Chip.waitForExistence(timeout: 15),
"Expected ⇧w3 chip for Exercise on demo Wednesday")
typeEventJumpChipLabel("⇧w3", in: window)
XCTAssertTrue(window.descendants(matching: .any)["compass-grid-event-focused"].waitForExistence(timeout: 8))
XCTAssertTrue(
window.buttons["Exercise"].waitForExistence(timeout: 4),
"Expected Shift+W3 jump to focus Exercise")
}
}
Loading