import XCTest import AppKit import SwiftUI import UniformTypeIdentifiers import WebKit import ObjectiveC.runtime import Bonsplit import UserNotifications #if canImport(cmux_DEV) @testable import cmux_DEV #elseif canImport(cmux) @testable import cmux #endif final class SplitShortcutTransientFocusGuardTests: XCTestCase { func testSuppressesWhenFirstResponderFallsBackAndHostedViewIsTiny() { XCTAssertTrue( shouldSuppressSplitShortcutForTransientTerminalFocusInputs( firstResponderIsWindow: true, hostedSize: CGSize(width: 79, height: 0), hostedHiddenInHierarchy: false, hostedAttachedToWindow: true ) ) } func testSuppressesWhenFirstResponderFallsBackAndHostedViewIsDetached() { XCTAssertTrue( shouldSuppressSplitShortcutForTransientTerminalFocusInputs( firstResponderIsWindow: true, hostedSize: CGSize(width: 1051.5, height: 1207), hostedHiddenInHierarchy: false, hostedAttachedToWindow: false ) ) } func testAllowsWhenFirstResponderFallsBackButGeometryIsHealthy() { XCTAssertFalse( shouldSuppressSplitShortcutForTransientTerminalFocusInputs( firstResponderIsWindow: true, hostedSize: CGSize(width: 1051.5, height: 1207), hostedHiddenInHierarchy: false, hostedAttachedToWindow: true ) ) } func testAllowsWhenFirstResponderIsTerminalEvenIfViewIsTiny() { XCTAssertFalse( shouldSuppressSplitShortcutForTransientTerminalFocusInputs( firstResponderIsWindow: false, hostedSize: CGSize(width: 79, height: 0), hostedHiddenInHierarchy: false, hostedAttachedToWindow: true ) ) } } final class FullScreenShortcutTests: XCTestCase { func testMatchesCommandControlF() { XCTAssertTrue( shouldToggleMainWindowFullScreenForCommandControlFShortcut( flags: [.command, .control], chars: "f", keyCode: 3 ) ) } func testMatchesCommandControlFFromKeyCodeWhenCharsAreUnavailable() { XCTAssertTrue( shouldToggleMainWindowFullScreenForCommandControlFShortcut( flags: [.command, .control], chars: "", keyCode: 3, layoutCharacterProvider: { _, _ in nil } ) ) } func testDoesNotFallbackToANSIWhenLayoutTranslationReturnsNonFCharacter() { XCTAssertFalse( shouldToggleMainWindowFullScreenForCommandControlFShortcut( flags: [.command, .control], chars: "", keyCode: 3, layoutCharacterProvider: { _, _ in "u" } ) ) } func testMatchesCommandControlFWhenCommandAwareLayoutTranslationProvidesF() { XCTAssertTrue( shouldToggleMainWindowFullScreenForCommandControlFShortcut( flags: [.command, .control], chars: "", keyCode: 3, layoutCharacterProvider: { _, modifierFlags in modifierFlags.contains(.command) ? "f" : "u" } ) ) } func testMatchesCommandControlFWhenCharsAreControlSequence() { XCTAssertTrue( shouldToggleMainWindowFullScreenForCommandControlFShortcut( flags: [.command, .control], chars: "\u{06}", keyCode: 3, layoutCharacterProvider: { _, _ in nil } ) ) } func testRejectsPhysicalFWhenCharacterRepresentsDifferentLayoutKey() { XCTAssertFalse( shouldToggleMainWindowFullScreenForCommandControlFShortcut( flags: [.command, .control], chars: "u", keyCode: 3 ) ) } func testIgnoresCapsLockForCommandControlF() { XCTAssertTrue( shouldToggleMainWindowFullScreenForCommandControlFShortcut( flags: [.command, .control, .capsLock], chars: "f", keyCode: 3 ) ) } func testRejectsWhenControlIsMissing() { XCTAssertFalse( shouldToggleMainWindowFullScreenForCommandControlFShortcut( flags: [.command], chars: "f", keyCode: 3 ) ) } func testRejectsAdditionalModifiers() { XCTAssertFalse( shouldToggleMainWindowFullScreenForCommandControlFShortcut( flags: [.command, .control, .shift], chars: "f", keyCode: 3 ) ) XCTAssertFalse( shouldToggleMainWindowFullScreenForCommandControlFShortcut( flags: [.command, .control, .option], chars: "f", keyCode: 3 ) ) } func testRejectsWhenCommandIsMissing() { XCTAssertFalse( shouldToggleMainWindowFullScreenForCommandControlFShortcut( flags: [.control], chars: "f", keyCode: 3 ) ) } func testRejectsNonFKey() { XCTAssertFalse( shouldToggleMainWindowFullScreenForCommandControlFShortcut( flags: [.command, .control], chars: "r", keyCode: 15 ) ) } } final class CommandPaletteKeyboardNavigationTests: XCTestCase { func testArrowKeysMoveSelectionWithoutModifiers() { XCTAssertEqual( commandPaletteSelectionDeltaForKeyboardNavigation( flags: [], chars: "", keyCode: 125 ), 1 ) XCTAssertEqual( commandPaletteSelectionDeltaForKeyboardNavigation( flags: [], chars: "", keyCode: 126 ), -1 ) XCTAssertNil( commandPaletteSelectionDeltaForKeyboardNavigation( flags: [.shift], chars: "", keyCode: 125 ) ) } func testControlLetterNavigationSupportsPrintableAndControlCharsForNPOnly() { XCTAssertEqual( commandPaletteSelectionDeltaForKeyboardNavigation( flags: [.control], chars: "n", keyCode: 45 ), 1 ) XCTAssertEqual( commandPaletteSelectionDeltaForKeyboardNavigation( flags: [.control], chars: "\u{0e}", keyCode: 45 ), 1 ) XCTAssertEqual( commandPaletteSelectionDeltaForKeyboardNavigation( flags: [.control], chars: "p", keyCode: 35 ), -1 ) XCTAssertEqual( commandPaletteSelectionDeltaForKeyboardNavigation( flags: [.control], chars: "\u{10}", keyCode: 35 ), -1 ) } func testDoesNotTreatControlJKAsPaletteNavigation() { XCTAssertNil( commandPaletteSelectionDeltaForKeyboardNavigation( flags: [.control], chars: "j", keyCode: 38 ) ) XCTAssertNil( commandPaletteSelectionDeltaForKeyboardNavigation( flags: [.control], chars: "\u{0a}", keyCode: 38 ) ) XCTAssertNil( commandPaletteSelectionDeltaForKeyboardNavigation( flags: [.control], chars: "k", keyCode: 40 ) ) XCTAssertNil( commandPaletteSelectionDeltaForKeyboardNavigation( flags: [.control], chars: "\u{0b}", keyCode: 40 ) ) } func testIgnoresUnsupportedModifiersAndKeys() { XCTAssertNil( commandPaletteSelectionDeltaForKeyboardNavigation( flags: [.command], chars: "n", keyCode: 45 ) ) XCTAssertNil( commandPaletteSelectionDeltaForKeyboardNavigation( flags: [.control, .shift], chars: "n", keyCode: 45 ) ) XCTAssertNil( commandPaletteSelectionDeltaForKeyboardNavigation( flags: [.control], chars: "x", keyCode: 7 ) ) } } final class CommandPaletteOpenShortcutConsumptionTests: XCTestCase { func testDoesNotConsumeWhenPaletteIsNotVisible() { XCTAssertFalse( shouldConsumeShortcutWhileCommandPaletteVisible( isCommandPaletteVisible: false, normalizedFlags: [.command], chars: "n", keyCode: 45 ) ) } func testConsumesAppCommandShortcutsWhenPaletteIsVisible() { XCTAssertTrue( shouldConsumeShortcutWhileCommandPaletteVisible( isCommandPaletteVisible: true, normalizedFlags: [.command], chars: "n", keyCode: 45 ) ) XCTAssertTrue( shouldConsumeShortcutWhileCommandPaletteVisible( isCommandPaletteVisible: true, normalizedFlags: [.command], chars: "t", keyCode: 17 ) ) XCTAssertTrue( shouldConsumeShortcutWhileCommandPaletteVisible( isCommandPaletteVisible: true, normalizedFlags: [.command, .shift], chars: ",", keyCode: 43 ) ) } func testAllowsClipboardAndUndoShortcutsForPaletteTextEditing() { XCTAssertFalse( shouldConsumeShortcutWhileCommandPaletteVisible( isCommandPaletteVisible: true, normalizedFlags: [.command], chars: "v", keyCode: 9 ) ) XCTAssertFalse( shouldConsumeShortcutWhileCommandPaletteVisible( isCommandPaletteVisible: true, normalizedFlags: [.command], chars: "z", keyCode: 6 ) ) XCTAssertFalse( shouldConsumeShortcutWhileCommandPaletteVisible( isCommandPaletteVisible: true, normalizedFlags: [.command, .shift], chars: "z", keyCode: 6 ) ) } func testAllowsArrowAndDeleteEditingCommandsForPaletteTextEditing() { XCTAssertFalse( shouldConsumeShortcutWhileCommandPaletteVisible( isCommandPaletteVisible: true, normalizedFlags: [.command], chars: "", keyCode: 123 ) ) XCTAssertFalse( shouldConsumeShortcutWhileCommandPaletteVisible( isCommandPaletteVisible: true, normalizedFlags: [.command], chars: "", keyCode: 51 ) ) } func testConsumesEscapeWhenPaletteIsVisible() { XCTAssertTrue( shouldConsumeShortcutWhileCommandPaletteVisible( isCommandPaletteVisible: true, normalizedFlags: [], chars: "", keyCode: 53 ) ) } } final class CommandPaletteFocusStealerClassificationTests: XCTestCase { private final class NonViewTextDelegate: NSObject, NSTextViewDelegate {} private final class UnrelatedViewTextDelegate: NSView, NSTextViewDelegate {} func testTreatsGhosttySurfaceViewAsFocusStealer() { let surfaceView = GhosttyNSView(frame: NSRect(x: 0, y: 0, width: 120, height: 80)) XCTAssertTrue(isCommandPaletteFocusStealingTerminalOrBrowserResponder(surfaceView)) } func testTreatsTextFieldInsideTerminalHostedViewAsFocusStealer() { let hostedView = GhosttySurfaceScrollView( surfaceView: GhosttyNSView(frame: NSRect(x: 0, y: 0, width: 120, height: 80)) ) let textField = NSTextField(frame: NSRect(x: 0, y: 0, width: 120, height: 24)) hostedView.addSubview(textField) XCTAssertTrue( isCommandPaletteFocusStealingTerminalOrBrowserResponder(textField), "Terminal-owned overlay text inputs should not be allowed to reclaim focus from the command palette" ) } func testDoesNotTreatUnrelatedTextFieldAsFocusStealer() { let textField = NSTextField(frame: NSRect(x: 0, y: 0, width: 120, height: 24)) XCTAssertFalse(isCommandPaletteFocusStealingTerminalOrBrowserResponder(textField)) } func testTreatsTextViewInsideTerminalHostedViewAsFocusStealerWhenDelegateIsNotAView() { let hostedView = GhosttySurfaceScrollView( surfaceView: GhosttyNSView(frame: NSRect(x: 0, y: 0, width: 120, height: 80)) ) let textView = NSTextView(frame: NSRect(x: 0, y: 0, width: 120, height: 24)) let delegate = NonViewTextDelegate() textView.delegate = delegate hostedView.addSubview(textView) XCTAssertTrue( isCommandPaletteFocusStealingTerminalOrBrowserResponder(textView), "NSTextView responders should still be blocked via the NSView hierarchy walk when the delegate is not a view" ) } func testTreatsTextViewInsideTerminalHostedViewAsFocusStealerWhenDelegateViewIsUnrelated() { let hostedView = GhosttySurfaceScrollView( surfaceView: GhosttyNSView(frame: NSRect(x: 0, y: 0, width: 120, height: 80)) ) let textView = NSTextView(frame: NSRect(x: 0, y: 0, width: 120, height: 24)) let delegateView = UnrelatedViewTextDelegate(frame: .zero) textView.delegate = delegateView hostedView.addSubview(textView) XCTAssertTrue( isCommandPaletteFocusStealingTerminalOrBrowserResponder(textView), "NSTextView responders should still be blocked via the NSView hierarchy walk when the delegate view is unrelated" ) } } final class CommandPaletteRestoreFocusStateMachineTests: XCTestCase { func testRestoresBrowserAddressBarWhenPaletteOpenedFromFocusedAddressBar() { let panelId = UUID() XCTAssertTrue( ContentView.shouldRestoreBrowserAddressBarAfterCommandPaletteDismiss( focusedPanelIsBrowser: true, focusedBrowserAddressBarPanelId: panelId, focusedPanelId: panelId ) ) } func testDoesNotRestoreBrowserAddressBarWhenFocusedPanelIsNotBrowser() { let panelId = UUID() XCTAssertFalse( ContentView.shouldRestoreBrowserAddressBarAfterCommandPaletteDismiss( focusedPanelIsBrowser: false, focusedBrowserAddressBarPanelId: panelId, focusedPanelId: panelId ) ) } func testDoesNotRestoreBrowserAddressBarWhenAnotherPanelHadAddressBarFocus() { XCTAssertFalse( ContentView.shouldRestoreBrowserAddressBarAfterCommandPaletteDismiss( focusedPanelIsBrowser: true, focusedBrowserAddressBarPanelId: UUID(), focusedPanelId: UUID() ) ) } } final class CommandPaletteRenameSelectionSettingsTests: XCTestCase { private let suiteName = "cmux.tests.commandPaletteRenameSelection.\(UUID().uuidString)" private func makeDefaults() -> UserDefaults { let defaults = UserDefaults(suiteName: suiteName)! defaults.removePersistentDomain(forName: suiteName) return defaults } func testDefaultsToSelectAllWhenUnset() { let defaults = makeDefaults() XCTAssertTrue(CommandPaletteRenameSelectionSettings.selectAllOnFocusEnabled(defaults: defaults)) } func testReturnsFalseWhenStoredFalse() { let defaults = makeDefaults() defaults.set(false, forKey: CommandPaletteRenameSelectionSettings.selectAllOnFocusKey) XCTAssertFalse(CommandPaletteRenameSelectionSettings.selectAllOnFocusEnabled(defaults: defaults)) } func testReturnsTrueWhenStoredTrue() { let defaults = makeDefaults() defaults.set(true, forKey: CommandPaletteRenameSelectionSettings.selectAllOnFocusKey) XCTAssertTrue(CommandPaletteRenameSelectionSettings.selectAllOnFocusEnabled(defaults: defaults)) } } final class CommandPaletteSelectionScrollBehaviorTests: XCTestCase { func testFirstEntryPinsToTopAnchor() { let anchor = ContentView.commandPaletteScrollPositionAnchor( selectedIndex: 0, resultCount: 20 ) XCTAssertEqual(anchor, UnitPoint.top) } func testLastEntryPinsToBottomAnchor() { let anchor = ContentView.commandPaletteScrollPositionAnchor( selectedIndex: 19, resultCount: 20 ) XCTAssertEqual(anchor, UnitPoint.bottom) } func testMiddleEntryUsesNilAnchorForMinimalScroll() { let anchor = ContentView.commandPaletteScrollPositionAnchor( selectedIndex: 6, resultCount: 20 ) XCTAssertNil(anchor) } func testEmptyResultsProduceNoAnchor() { let anchor = ContentView.commandPaletteScrollPositionAnchor( selectedIndex: 0, resultCount: 0 ) XCTAssertNil(anchor) } } final class ShortcutHintModifierPolicyTests: XCTestCase { func testShortcutHintRequiresEnabledCommandOnlyModifier() { withDefaultsSuite { defaults in defaults.set(true, forKey: ShortcutHintDebugSettings.showHintsOnCommandHoldKey) XCTAssertTrue(ShortcutHintModifierPolicy.shouldShowHints(for: [.command], defaults: defaults)) XCTAssertFalse(ShortcutHintModifierPolicy.shouldShowHints(for: [.control], defaults: defaults)) XCTAssertFalse(ShortcutHintModifierPolicy.shouldShowHints(for: [], defaults: defaults)) XCTAssertFalse(ShortcutHintModifierPolicy.shouldShowHints(for: [.command, .shift], defaults: defaults)) XCTAssertFalse(ShortcutHintModifierPolicy.shouldShowHints(for: [.control, .shift], defaults: defaults)) XCTAssertFalse(ShortcutHintModifierPolicy.shouldShowHints(for: [.command, .option], defaults: defaults)) XCTAssertFalse(ShortcutHintModifierPolicy.shouldShowHints(for: [.control, .option], defaults: defaults)) XCTAssertFalse(ShortcutHintModifierPolicy.shouldShowHints(for: [.command, .control], defaults: defaults)) } } func testCommandHintCanBeDisabledInSettings() { withDefaultsSuite { defaults in defaults.set(false, forKey: ShortcutHintDebugSettings.showHintsOnCommandHoldKey) XCTAssertFalse(ShortcutHintModifierPolicy.shouldShowHints(for: [.command], defaults: defaults)) XCTAssertFalse(ShortcutHintModifierPolicy.shouldShowHints(for: [.control], defaults: defaults)) } } func testCommandHintDefaultsToEnabledWhenSettingMissing() { withDefaultsSuite { defaults in defaults.removeObject(forKey: ShortcutHintDebugSettings.showHintsOnCommandHoldKey) XCTAssertTrue(ShortcutHintModifierPolicy.shouldShowHints(for: [.command], defaults: defaults)) XCTAssertFalse(ShortcutHintModifierPolicy.shouldShowHints(for: [.control], defaults: defaults)) } } func testShortcutHintUsesIntentionalHoldDelay() { XCTAssertEqual(ShortcutHintModifierPolicy.intentionalHoldDelay, 0.30, accuracy: 0.001) } func testCurrentWindowRequiresHostWindowToBeKeyAndMatchEventWindow() { XCTAssertTrue( ShortcutHintModifierPolicy.isCurrentWindow( hostWindowNumber: 42, hostWindowIsKey: true, eventWindowNumber: 42, keyWindowNumber: 42 ) ) XCTAssertFalse( ShortcutHintModifierPolicy.isCurrentWindow( hostWindowNumber: 42, hostWindowIsKey: true, eventWindowNumber: 7, keyWindowNumber: 42 ) ) XCTAssertFalse( ShortcutHintModifierPolicy.isCurrentWindow( hostWindowNumber: 42, hostWindowIsKey: false, eventWindowNumber: 42, keyWindowNumber: 42 ) ) } func testWindowScopedShortcutHintsUseKeyWindowWhenNoEventWindowIsAvailable() { withDefaultsSuite { defaults in defaults.set(true, forKey: ShortcutHintDebugSettings.showHintsOnCommandHoldKey) XCTAssertTrue( ShortcutHintModifierPolicy.shouldShowHints( for: [.command], hostWindowNumber: 42, hostWindowIsKey: true, eventWindowNumber: nil, keyWindowNumber: 42, defaults: defaults ) ) XCTAssertFalse( ShortcutHintModifierPolicy.shouldShowHints( for: [.command], hostWindowNumber: 42, hostWindowIsKey: true, eventWindowNumber: nil, keyWindowNumber: 7, defaults: defaults ) ) XCTAssertTrue( ShortcutHintModifierPolicy.shouldShowHints( for: [.command], hostWindowNumber: 42, hostWindowIsKey: true, eventWindowNumber: nil, keyWindowNumber: 42, defaults: defaults ) ) XCTAssertFalse( ShortcutHintModifierPolicy.shouldShowHints( for: [.control], hostWindowNumber: 42, hostWindowIsKey: true, eventWindowNumber: nil, keyWindowNumber: 42, defaults: defaults ) ) } } private func withDefaultsSuite(_ body: (UserDefaults) -> Void) { let suiteName = "ShortcutHintModifierPolicyTests-\(UUID().uuidString)" guard let defaults = UserDefaults(suiteName: suiteName) else { XCTFail("Failed to create defaults suite") return } defaults.removePersistentDomain(forName: suiteName) body(defaults) defaults.removePersistentDomain(forName: suiteName) } } final class ShortcutHintDebugSettingsTests: XCTestCase { func testClampKeepsValuesWithinSupportedRange() { XCTAssertEqual(ShortcutHintDebugSettings.clamped(0.0), 0.0) XCTAssertEqual(ShortcutHintDebugSettings.clamped(4.0), 4.0) XCTAssertEqual(ShortcutHintDebugSettings.clamped(-100.0), ShortcutHintDebugSettings.offsetRange.lowerBound) XCTAssertEqual(ShortcutHintDebugSettings.clamped(100.0), ShortcutHintDebugSettings.offsetRange.upperBound) } func testDefaultOffsetsMatchCurrentBadgePlacements() { XCTAssertEqual(ShortcutHintDebugSettings.defaultSidebarHintX, 0.0) XCTAssertEqual(ShortcutHintDebugSettings.defaultSidebarHintY, 0.0) XCTAssertEqual(ShortcutHintDebugSettings.defaultTitlebarHintX, 4.0) XCTAssertEqual(ShortcutHintDebugSettings.defaultTitlebarHintY, 0.0) XCTAssertEqual(ShortcutHintDebugSettings.defaultPaneHintX, 0.0) XCTAssertEqual(ShortcutHintDebugSettings.defaultPaneHintY, 0.0) XCTAssertFalse(ShortcutHintDebugSettings.defaultAlwaysShowHints) XCTAssertTrue(ShortcutHintDebugSettings.defaultShowHintsOnCommandHold) } func testShowHintsOnCommandHoldSettingRespectsStoredValue() { let suiteName = "ShortcutHintDebugSettingsTests-\(UUID().uuidString)" guard let defaults = UserDefaults(suiteName: suiteName) else { XCTFail("Failed to create defaults suite") return } defaults.removePersistentDomain(forName: suiteName) defer { defaults.removePersistentDomain(forName: suiteName) } defaults.removeObject(forKey: ShortcutHintDebugSettings.showHintsOnCommandHoldKey) XCTAssertTrue(ShortcutHintDebugSettings.showHintsOnCommandHoldEnabled(defaults: defaults)) defaults.set(false, forKey: ShortcutHintDebugSettings.showHintsOnCommandHoldKey) XCTAssertFalse(ShortcutHintDebugSettings.showHintsOnCommandHoldEnabled(defaults: defaults)) defaults.set(true, forKey: ShortcutHintDebugSettings.showHintsOnCommandHoldKey) XCTAssertTrue(ShortcutHintDebugSettings.showHintsOnCommandHoldEnabled(defaults: defaults)) } func testResetVisibilityDefaultsRestoresAlwaysShowAndCommandHoldFlags() { let suiteName = "ShortcutHintDebugSettingsTests-\(UUID().uuidString)" guard let defaults = UserDefaults(suiteName: suiteName) else { XCTFail("Failed to create defaults suite") return } defaults.removePersistentDomain(forName: suiteName) defer { defaults.removePersistentDomain(forName: suiteName) } defaults.set(true, forKey: ShortcutHintDebugSettings.alwaysShowHintsKey) defaults.set(false, forKey: ShortcutHintDebugSettings.showHintsOnCommandHoldKey) ShortcutHintDebugSettings.resetVisibilityDefaults(defaults: defaults) XCTAssertEqual( defaults.object(forKey: ShortcutHintDebugSettings.alwaysShowHintsKey) as? Bool, ShortcutHintDebugSettings.defaultAlwaysShowHints ) XCTAssertEqual( defaults.object(forKey: ShortcutHintDebugSettings.showHintsOnCommandHoldKey) as? Bool, ShortcutHintDebugSettings.defaultShowHintsOnCommandHold ) } } final class DevBuildBannerDebugSettingsTests: XCTestCase { func testShowSidebarBannerDefaultsToVisible() { let suiteName = "DevBuildBannerDebugSettingsTests.Default.\(UUID().uuidString)" guard let defaults = UserDefaults(suiteName: suiteName) else { XCTFail("Failed to create isolated UserDefaults suite") return } defer { defaults.removePersistentDomain(forName: suiteName) } defaults.removeObject(forKey: DevBuildBannerDebugSettings.sidebarBannerVisibleKey) XCTAssertTrue(DevBuildBannerDebugSettings.showSidebarBanner(defaults: defaults)) } func testShowSidebarBannerRespectsStoredValue() { let suiteName = "DevBuildBannerDebugSettingsTests.Stored.\(UUID().uuidString)" guard let defaults = UserDefaults(suiteName: suiteName) else { XCTFail("Failed to create isolated UserDefaults suite") return } defer { defaults.removePersistentDomain(forName: suiteName) } defaults.set(false, forKey: DevBuildBannerDebugSettings.sidebarBannerVisibleKey) XCTAssertFalse(DevBuildBannerDebugSettings.showSidebarBanner(defaults: defaults)) defaults.set(true, forKey: DevBuildBannerDebugSettings.sidebarBannerVisibleKey) XCTAssertTrue(DevBuildBannerDebugSettings.showSidebarBanner(defaults: defaults)) } } final class ShortcutHintLanePlannerTests: XCTestCase { func testAssignLanesKeepsSeparatedIntervalsOnSingleLane() { let intervals: [ClosedRange] = [0...20, 28...40, 48...64] XCTAssertEqual(ShortcutHintLanePlanner.assignLanes(for: intervals, minSpacing: 4), [0, 0, 0]) } func testAssignLanesStacksOverlappingIntervalsIntoAdditionalLanes() { let intervals: [ClosedRange] = [0...20, 18...34, 22...38, 40...56] XCTAssertEqual(ShortcutHintLanePlanner.assignLanes(for: intervals, minSpacing: 4), [0, 1, 2, 0]) } } final class ShortcutHintHorizontalPlannerTests: XCTestCase { func testAssignRightEdgesResolvesOverlapWithMinimumSpacing() { let intervals: [ClosedRange] = [0...20, 18...34, 30...46] let rightEdges = ShortcutHintHorizontalPlanner.assignRightEdges(for: intervals, minSpacing: 6) XCTAssertEqual(rightEdges.count, intervals.count) let adjustedIntervals = zip(intervals, rightEdges).map { interval, rightEdge in let width = interval.upperBound - interval.lowerBound return (rightEdge - width)...rightEdge } XCTAssertGreaterThanOrEqual(adjustedIntervals[1].lowerBound - adjustedIntervals[0].upperBound, 6) XCTAssertGreaterThanOrEqual(adjustedIntervals[2].lowerBound - adjustedIntervals[1].upperBound, 6) } func testAssignRightEdgesKeepsAlreadySeparatedIntervalsInPlace() { let intervals: [ClosedRange] = [0...12, 20...32, 40...52] let rightEdges = ShortcutHintHorizontalPlanner.assignRightEdges(for: intervals, minSpacing: 4) XCTAssertEqual(rightEdges, [12, 32, 52]) } } final class LastSurfaceCloseShortcutSettingsTests: XCTestCase { func testDefaultClosesWorkspace() { let suiteName = "LastSurfaceCloseShortcutSettingsTests.Default.\(UUID().uuidString)" guard let defaults = UserDefaults(suiteName: suiteName) else { XCTFail("Failed to create isolated UserDefaults suite") return } defer { defaults.removePersistentDomain(forName: suiteName) } XCTAssertTrue(LastSurfaceCloseShortcutSettings.closesWorkspace(defaults: defaults)) } func testStoredTrueClosesWorkspace() { let suiteName = "LastSurfaceCloseShortcutSettingsTests.Enabled.\(UUID().uuidString)" guard let defaults = UserDefaults(suiteName: suiteName) else { XCTFail("Failed to create isolated UserDefaults suite") return } defer { defaults.removePersistentDomain(forName: suiteName) } defaults.set(true, forKey: LastSurfaceCloseShortcutSettings.key) XCTAssertTrue(LastSurfaceCloseShortcutSettings.closesWorkspace(defaults: defaults)) } func testStoredFalseKeepsWorkspaceOpen() { let suiteName = "LastSurfaceCloseShortcutSettingsTests.Disabled.\(UUID().uuidString)" guard let defaults = UserDefaults(suiteName: suiteName) else { XCTFail("Failed to create isolated UserDefaults suite") return } defer { defaults.removePersistentDomain(forName: suiteName) } defaults.set(false, forKey: LastSurfaceCloseShortcutSettings.key) XCTAssertFalse(LastSurfaceCloseShortcutSettings.closesWorkspace(defaults: defaults)) } } final class AppearanceSettingsTests: XCTestCase { func testResolvedModeDefaultsToSystemWhenUnset() { let suiteName = "AppearanceSettingsTests.Default.\(UUID().uuidString)" guard let defaults = UserDefaults(suiteName: suiteName) else { XCTFail("Failed to create isolated UserDefaults suite") return } defer { defaults.removePersistentDomain(forName: suiteName) } defaults.removeObject(forKey: AppearanceSettings.appearanceModeKey) let resolved = AppearanceSettings.resolvedMode(defaults: defaults) XCTAssertEqual(resolved, .system) XCTAssertEqual(defaults.string(forKey: AppearanceSettings.appearanceModeKey), AppearanceMode.system.rawValue) } } final class QuitWarningSettingsTests: XCTestCase { func testDefaultWarnBeforeQuitIsEnabledWhenUnset() { let suiteName = "QuitWarningSettingsTests.Default.\(UUID().uuidString)" guard let defaults = UserDefaults(suiteName: suiteName) else { XCTFail("Failed to create isolated UserDefaults suite") return } defer { defaults.removePersistentDomain(forName: suiteName) } defaults.removeObject(forKey: QuitWarningSettings.warnBeforeQuitKey) XCTAssertTrue(QuitWarningSettings.isEnabled(defaults: defaults)) } func testStoredPreferenceOverridesDefault() { let suiteName = "QuitWarningSettingsTests.Stored.\(UUID().uuidString)" guard let defaults = UserDefaults(suiteName: suiteName) else { XCTFail("Failed to create isolated UserDefaults suite") return } defer { defaults.removePersistentDomain(forName: suiteName) } defaults.set(false, forKey: QuitWarningSettings.warnBeforeQuitKey) XCTAssertFalse(QuitWarningSettings.isEnabled(defaults: defaults)) defaults.set(true, forKey: QuitWarningSettings.warnBeforeQuitKey) XCTAssertTrue(QuitWarningSettings.isEnabled(defaults: defaults)) } } final class UpdateChannelSettingsTests: XCTestCase { func testResolvedFeedFallsBackWhenInfoFeedMissing() { let resolved = UpdateFeedResolver.resolvedFeedURLString(infoFeedURL: nil) XCTAssertEqual(resolved.url, UpdateFeedResolver.fallbackFeedURL) XCTAssertFalse(resolved.isNightly) XCTAssertTrue(resolved.usedFallback) } func testResolvedFeedFallsBackWhenInfoFeedEmpty() { let resolved = UpdateFeedResolver.resolvedFeedURLString(infoFeedURL: "") XCTAssertEqual(resolved.url, UpdateFeedResolver.fallbackFeedURL) XCTAssertFalse(resolved.isNightly) XCTAssertTrue(resolved.usedFallback) } func testResolvedFeedUsesInfoFeedForStableChannel() { let infoFeed = "https://example.com/custom/appcast.xml" let resolved = UpdateFeedResolver.resolvedFeedURLString(infoFeedURL: infoFeed) XCTAssertEqual(resolved.url, infoFeed) XCTAssertFalse(resolved.isNightly) XCTAssertFalse(resolved.usedFallback) } func testResolvedFeedDetectsNightlyFromInfoFeedURL() { let resolved = UpdateFeedResolver.resolvedFeedURLString( infoFeedURL: "https://example.com/nightly/appcast.xml" ) XCTAssertEqual(resolved.url, "https://example.com/nightly/appcast.xml") XCTAssertTrue(resolved.isNightly) XCTAssertFalse(resolved.usedFallback) } } final class UpdateSettingsTests: XCTestCase { func testApplyEnablesAutomaticChecksAndDailySchedule() { let defaults = makeDefaults() UpdateSettings.apply(to: defaults) XCTAssertTrue(defaults.bool(forKey: UpdateSettings.automaticChecksKey)) XCTAssertEqual(defaults.double(forKey: UpdateSettings.scheduledCheckIntervalKey), UpdateSettings.scheduledCheckInterval) XCTAssertFalse(defaults.bool(forKey: UpdateSettings.automaticallyUpdateKey)) XCTAssertFalse(defaults.bool(forKey: UpdateSettings.sendProfileInfoKey)) XCTAssertTrue(defaults.bool(forKey: UpdateSettings.migrationKey)) } func testApplyRepairsLegacyDisabledAutomaticChecksOnce() { let defaults = makeDefaults() defaults.set(false, forKey: UpdateSettings.automaticChecksKey) defaults.set(0, forKey: UpdateSettings.scheduledCheckIntervalKey) defaults.set(true, forKey: UpdateSettings.automaticallyUpdateKey) UpdateSettings.apply(to: defaults) XCTAssertTrue(defaults.bool(forKey: UpdateSettings.automaticChecksKey)) XCTAssertEqual(defaults.double(forKey: UpdateSettings.scheduledCheckIntervalKey), UpdateSettings.scheduledCheckInterval) XCTAssertTrue(defaults.bool(forKey: UpdateSettings.automaticallyUpdateKey)) defaults.set(false, forKey: UpdateSettings.automaticChecksKey) UpdateSettings.apply(to: defaults) XCTAssertFalse(defaults.bool(forKey: UpdateSettings.automaticChecksKey)) } private func makeDefaults() -> UserDefaults { let suiteName = "UpdateSettingsTests.\(UUID().uuidString)" guard let defaults = UserDefaults(suiteName: suiteName) else { fatalError("Failed to create isolated UserDefaults suite") } defaults.removePersistentDomain(forName: suiteName) return defaults } } final class UpdateViewModelPresentationTests: XCTestCase { func testDetectedBackgroundUpdateShowsPillWhileIdle() { let viewModel = UpdateViewModel() viewModel.detectedUpdateVersion = "9.9.9" XCTAssertTrue(viewModel.showsPill) XCTAssertTrue(viewModel.showsDetectedBackgroundUpdate) XCTAssertEqual(viewModel.text, "Update Available: 9.9.9") XCTAssertEqual(viewModel.iconName, "shippingbox.fill") } func testActiveUpdateStateTakesPrecedenceOverDetectedBackgroundVersion() { let viewModel = UpdateViewModel() viewModel.detectedUpdateVersion = "9.9.9" viewModel.state = .checking(.init(cancel: {})) XCTAssertTrue(viewModel.showsPill) XCTAssertFalse(viewModel.showsDetectedBackgroundUpdate) XCTAssertEqual(viewModel.text, "Checking for Updates…") } } @MainActor final class CommandPaletteOverlayPromotionPolicyTests: XCTestCase { func testShouldPromoteWhenBecomingVisible() { XCTAssertTrue( CommandPaletteOverlayPromotionPolicy.shouldPromote( previouslyVisible: false, isVisible: true ) ) } func testShouldNotPromoteWhenAlreadyVisible() { XCTAssertFalse( CommandPaletteOverlayPromotionPolicy.shouldPromote( previouslyVisible: true, isVisible: true ) ) } func testShouldNotPromoteWhenHidden() { XCTAssertFalse( CommandPaletteOverlayPromotionPolicy.shouldPromote( previouslyVisible: true, isVisible: false ) ) XCTAssertFalse( CommandPaletteOverlayPromotionPolicy.shouldPromote( previouslyVisible: false, isVisible: false ) ) } }