Files
downterm/CommandNotch/CommandNotchTests/WorkspaceRegistryTests.swift
2026-03-13 21:26:06 +11:00

147 lines
5.5 KiB
Swift

import XCTest
@testable import CommandNotch
@MainActor
final class WorkspaceRegistryTests: XCTestCase {
func testRegistryCreatesDefaultWorkspaceWhenEmpty() {
let registry = makeRegistry()
XCTAssertEqual(registry.allWorkspaceSummaries().count, 1)
XCTAssertEqual(registry.allWorkspaceSummaries().first?.name, "Main")
XCTAssertNotNil(registry.controller(for: registry.defaultWorkspaceID))
}
func testCreateRenameAndDeleteWorkspaceUpdatesSummaries() {
let registry = makeRegistry()
let createdID = registry.createWorkspace(named: "Docs")
XCTAssertEqual(registry.allWorkspaceSummaries().map(\.name), ["Main", "Docs"])
registry.renameWorkspace(id: createdID, to: "Review")
XCTAssertEqual(registry.allWorkspaceSummaries().map(\.name), ["Main", "Review"])
registry.deleteWorkspace(id: createdID)
XCTAssertEqual(registry.allWorkspaceSummaries().map(\.name), ["Main"])
}
func testDeletingLastWorkspaceIsIgnored() {
let registry = makeRegistry()
let onlyWorkspaceID = registry.defaultWorkspaceID
registry.deleteWorkspace(id: onlyWorkspaceID)
XCTAssertEqual(registry.allWorkspaceSummaries().count, 1)
XCTAssertEqual(registry.allWorkspaceSummaries().first?.id, onlyWorkspaceID)
}
func testDeletionFallbackPrefersRequestedWorkspaceWhenAvailable() {
let registry = makeRegistry()
let docsID = registry.createWorkspace(named: "Docs")
let reviewID = registry.createWorkspace(named: "Review")
let fallback = registry.deletionFallbackWorkspaceID(
forDeleting: docsID,
preferredFallback: reviewID
)
XCTAssertEqual(fallback, reviewID)
}
func testRegistryLoadsPersistedWorkspacesFromStore() {
let store = InMemoryWorkspaceStore()
let docsID = UUID(uuidString: "11111111-1111-1111-1111-111111111111")!
store.savedSummaries = [WorkspaceSummary(id: docsID, name: "Docs")]
let registry = makeRegistry(initialWorkspaces: nil, store: store)
XCTAssertEqual(registry.allWorkspaceSummaries().count, 1)
XCTAssertEqual(registry.allWorkspaceSummaries().first?.id, docsID)
XCTAssertEqual(registry.allWorkspaceSummaries().first?.name, "Docs")
XCTAssertEqual(registry.defaultWorkspaceID, docsID)
}
func testRegistryPersistsWorkspaceSummaryChanges() {
let store = InMemoryWorkspaceStore()
let registry = makeRegistry(store: store)
let createdID = registry.createWorkspace(named: "Docs")
XCTAssertEqual(store.savedSummaries.map(\.name), ["Main", "Docs"])
registry.renameWorkspace(id: createdID, to: "Review")
XCTAssertEqual(store.savedSummaries.map(\.name), ["Main", "Review"])
registry.deleteWorkspace(id: createdID)
XCTAssertEqual(store.savedSummaries.map(\.name), ["Main"])
}
func testUpdateWorkspaceHotkeyPersistsAndUpdatesSummary() {
let store = InMemoryWorkspaceStore()
let registry = makeRegistry(store: store)
let docsID = registry.createWorkspace(named: "Docs")
let hotkey = HotkeyBinding.cmdShiftDigit(4)
registry.updateWorkspaceHotkey(id: docsID, to: hotkey)
XCTAssertEqual(registry.summary(for: docsID)?.hotkey, hotkey)
XCTAssertEqual(store.savedSummaries.last?.hotkey, hotkey)
}
func testNextAndPreviousWorkspaceWrapAroundRegistryOrder() {
let registry = makeRegistry()
let mainID = registry.defaultWorkspaceID
let docsID = registry.createWorkspace(named: "Docs")
let reviewID = registry.createWorkspace(named: "Review")
XCTAssertEqual(registry.nextWorkspaceID(after: mainID), docsID)
XCTAssertEqual(registry.nextWorkspaceID(after: reviewID), mainID)
XCTAssertEqual(registry.previousWorkspaceID(before: mainID), reviewID)
XCTAssertEqual(registry.previousWorkspaceID(before: docsID), mainID)
}
private func makeRegistry(
initialWorkspaces: [WorkspaceSummary]? = [],
store: (any WorkspaceStoreType)? = nil
) -> WorkspaceRegistry {
let settingsProvider = TestSettingsProvider()
let sessionFactory = UnusedTerminalSessionFactory()
return WorkspaceRegistry(
initialWorkspaces: initialWorkspaces,
store: store,
controllerFactory: { summary in
WorkspaceController(
summary: summary,
sessionFactory: sessionFactory,
settingsProvider: settingsProvider,
bootstrapDefaultTab: false
)
}
)
}
}
private final class InMemoryWorkspaceStore: WorkspaceStoreType {
var savedSummaries: [WorkspaceSummary] = []
func loadWorkspaceSummaries() -> [WorkspaceSummary] {
savedSummaries
}
func saveWorkspaceSummaries(_ summaries: [WorkspaceSummary]) {
savedSummaries = summaries
}
}
private final class TestSettingsProvider: TerminalSessionConfigurationProviding {
let terminalSessionConfiguration = TerminalSessionConfiguration(fontSize: 13, theme: .terminalApp, shellPath: "")
let hotkeySettings = AppSettings.default.hotkeys
let terminalSizePresets = TerminalSizePresetStore.loadDefaults()
}
private struct UnusedTerminalSessionFactory: TerminalSessionFactoryType {
@MainActor
func makeSession(fontSize: CGFloat, theme: TerminalTheme, shellPath: String) -> TerminalSession {
fatalError("WorkspaceRegistryTests should not create live terminal sessions.")
}
}