Skip to content
Merged
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
31 changes: 26 additions & 5 deletions Sources/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15350,6 +15350,7 @@ struct SidebarFooterButtons: View {
}

private enum SidebarHelpMenuAction {
case settings
case upgrade
case importBrowserData
case keyboardShortcuts
Expand Down Expand Up @@ -15400,6 +15401,11 @@ private struct SidebarHelpMenuButton: View {
#endif
}

private var settingsShortcutHint: String {
let _ = keyboardShortcutSettingsObserver.revision
return KeyboardShortcutSettings.shortcut(for: .openSettings).displayString
}

private var sendFeedbackShortcutHint: String {
let _ = keyboardShortcutSettingsObserver.revision
return KeyboardShortcutSettings.shortcut(for: .sendFeedback).displayString
Expand Down Expand Up @@ -15445,12 +15451,11 @@ private struct SidebarHelpMenuButton: View {
)
}
helpOptionButton(
title: String(localized: "sidebar.help.sendFeedback", defaultValue: "Send Feedback"),
action: .sendFeedback,
accessibilityIdentifier: "SidebarHelpMenuOptionSendFeedback",
title: String(localized: "menu.app.settings", defaultValue: "Settings…"),
action: .settings,
accessibilityIdentifier: "SidebarHelpMenuOptionSettings",
isExternalLink: false,
shortcutHint: sendFeedbackShortcutHint,
trailingSystemImage: "bubble.left.and.text.bubble.right"
shortcutHint: settingsShortcutHint
)
helpOptionButton(
title: String(localized: "settings.section.keyboardShortcuts", defaultValue: "Keyboard Shortcuts"),
Expand All @@ -15464,6 +15469,14 @@ private struct SidebarHelpMenuButton: View {
accessibilityIdentifier: "SidebarHelpMenuOptionImportBrowserData",
isExternalLink: false
)
helpOptionButton(
title: String(localized: "sidebar.help.sendFeedback", defaultValue: "Send Feedback"),
action: .sendFeedback,
accessibilityIdentifier: "SidebarHelpMenuOptionSendFeedback",
isExternalLink: false,
shortcutHint: sendFeedbackShortcutHint,
trailingSystemImage: "bubble.left.and.text.bubble.right"
)
if docsURL != nil {
helpOptionButton(
title: String(localized: "about.docs", defaultValue: "Docs"),
Expand Down Expand Up @@ -15564,6 +15577,14 @@ private struct SidebarHelpMenuButton: View {

private func perform(_ action: SidebarHelpMenuAction) {
switch action {
case .settings:
Task { @MainActor in
if let appDelegate = AppDelegate.shared {
appDelegate.openPreferencesWindow(debugSource: "sidebarHelpMenu.settings")
} else {
AppDelegate.presentPreferencesWindow()
}
}
case .upgrade:
ProUpgradePresenter.present(source: .sidebarHelpMenu)
case .importBrowserData:
Expand Down
1 change: 1 addition & 0 deletions Sources/Workspace+AgentResumeOwnership.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import CmuxFoundation
import CMUXAgentLaunch
import CmuxFoundation
import Foundation
Expand Down
99 changes: 99 additions & 0 deletions cmuxUITests/SidebarHelpMenuUITests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,104 @@ final class SidebarHelpMenuUITests: XCTestCase {
XCTAssertTrue(app.staticTexts["5/4000"].waitForExistence(timeout: 2.0))
}

func testHelpMenuSettingsOpensDismissesAndReopensWithShortcut() {
let app = XCUIApplication.cmuxTestApplication()
app.launchArguments += [
"-AppleLanguages", "(en)",
"-AppleLocale", "en_US",
"-ApplePersistenceIgnoreState", "YES",
"-NSQuitAlwaysKeepsWindows", "NO",
"-menuBarOnly", "false",
]
app.launchEnvironment["CMUX_UI_TEST_MODE"] = "1"
app.launch()
XCTAssertTrue(
sidebarHelpPollUntil(timeout: 10.0) {
app.state == .runningForeground || app.state == .runningBackground
},
"App failed to launch. state=\(app.state.rawValue)"
)
app.activate()
XCTAssertTrue(
sidebarHelpPollUntil(timeout: 6.0) { app.state == .runningForeground },
"App did not become foreground before interactions. state=\(app.state.rawValue)"
)

XCTAssertTrue(waitForWindowCount(atLeast: 1, app: app, timeout: 10.0))

let helpButton = requireElement(
candidates: helpButtonCandidates(in: app),
timeout: 6.0,
description: "sidebar help button"
)
helpButton.click()

let settingsItem = requireElement(
candidates: helpMenuItemCandidates(
in: app,
identifier: "SidebarHelpMenuOptionSettings",
title: "Settings…"
),
timeout: 3.0,
description: "Settings help menu item"
)
settingsItem.click()

let settings = app.windows["Settings"]
XCTAssertTrue(
sidebarHelpPollUntil(timeout: 6.0) { settings.exists },
"Expected Settings to open from the sidebar Help menu"
)
XCTAssertTrue(
sidebarHelpPollUntil(timeout: 2.0) {
!app.buttons["SidebarHelpMenuOptionSettings"].exists
&& !app.buttons["Settings…"].exists
},
"Expected the Help popover to dismiss after opening Settings"
)
XCTAssertEqual(app.windows.count, 2, "Expected one main window and one Settings window")

settings.typeKey("w", modifierFlags: [.command])
XCTAssertTrue(
sidebarHelpPollUntil(timeout: 3.0) { app.windows.count == 1 && !settings.exists },
"Expected Cmd+W to close Settings and return to the main window"
)

helpButton.click()
let reopenedSettingsItem = requireElement(
candidates: helpMenuItemCandidates(
in: app,
identifier: "SidebarHelpMenuOptionSettings",
title: "Settings…"
),
timeout: 3.0,
description: "Settings help menu item after closing Settings"
)
reopenedSettingsItem.click()
XCTAssertTrue(
sidebarHelpPollUntil(timeout: 6.0) { app.windows["Settings"].exists },
"Expected the Help menu to reopen Settings after closing it"
)

settings.typeKey("w", modifierFlags: [.command])
XCTAssertTrue(
sidebarHelpPollUntil(timeout: 3.0) { app.windows.count == 1 && !settings.exists },
"Expected Settings to close before exercising Cmd+,"
)

app.typeKey(",", modifierFlags: [.command])
XCTAssertTrue(
sidebarHelpPollUntil(timeout: 6.0) { settings.exists && app.windows.count == 2 },
"Expected Cmd+, to reopen the existing Settings surface"
)
app.typeKey(",", modifierFlags: [.command])
XCTAssertEqual(
app.windows.count,
2,
"Expected a repeated Cmd+, to reuse the single Settings window instead of creating a duplicate"
)
}

private func waitForWindowCount(atLeast count: Int, app: XCUIApplication, timeout: TimeInterval) -> Bool {
sidebarHelpPollUntil(timeout: timeout) {
app.windows.count >= count
Expand All @@ -136,6 +234,7 @@ final class SidebarHelpMenuUITests: XCTestCase {
app.buttons["Help"],
sidebar.buttons["SidebarHelpMenuButton"],
sidebar.buttons["Help"],
app.descendants(matching: .any).matching(NSPredicate(format: "label == %@", "Help")).firstMatch,
]
}

Expand Down
Loading