231 lines
8.2 KiB
Swift
231 lines
8.2 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
|
|
)
|
|
}
|
|
)
|
|
}
|
|
}
|
|
|
|
@MainActor
|
|
final class WorkspaceControllerTests: XCTestCase {
|
|
func testNewTabUsesActiveTabCurrentDirectory() {
|
|
let factory = RecordingTerminalSessionFactory()
|
|
let controller = WorkspaceController(
|
|
summary: WorkspaceSummary(name: "Main"),
|
|
sessionFactory: factory,
|
|
settingsProvider: TestSettingsProvider(),
|
|
bootstrapDefaultTab: false
|
|
)
|
|
|
|
controller.newTab()
|
|
controller.activeTab?.currentDirectory = "/tmp/Raycast"
|
|
|
|
controller.newTab()
|
|
|
|
XCTAssertEqual(factory.requestedDirectories, [nil, "/tmp/Raycast"])
|
|
XCTAssertEqual(controller.activeTab?.currentDirectory, "/tmp/Raycast")
|
|
XCTAssertEqual(controller.tabs.count, 2)
|
|
XCTAssertEqual(controller.activeTabIndex, 1)
|
|
}
|
|
|
|
func testNewTabNormalizesCurrentDirectoryFileURL() {
|
|
let factory = RecordingTerminalSessionFactory()
|
|
let controller = WorkspaceController(
|
|
summary: WorkspaceSummary(name: "Main"),
|
|
sessionFactory: factory,
|
|
settingsProvider: TestSettingsProvider(),
|
|
bootstrapDefaultTab: false
|
|
)
|
|
let expectedPath = "/tmp/Raycast Folder"
|
|
|
|
controller.newTab()
|
|
controller.activeTab?.currentDirectory = URL(fileURLWithPath: expectedPath).absoluteString
|
|
|
|
controller.newTab()
|
|
|
|
XCTAssertEqual(controller.activeTab?.currentDirectory, expectedPath)
|
|
}
|
|
|
|
func testNewTabFallsBackToHomeDirectoryWhenWorkspaceHasNoTabs() {
|
|
let factory = RecordingTerminalSessionFactory()
|
|
let controller = WorkspaceController(
|
|
summary: WorkspaceSummary(name: "Main"),
|
|
sessionFactory: factory,
|
|
settingsProvider: TestSettingsProvider(),
|
|
bootstrapDefaultTab: false
|
|
)
|
|
|
|
controller.newTab()
|
|
|
|
XCTAssertEqual(factory.requestedDirectories, [nil])
|
|
XCTAssertEqual(controller.activeTab?.currentDirectory, NSHomeDirectory())
|
|
XCTAssertEqual(controller.tabs.count, 1)
|
|
XCTAssertEqual(controller.activeTabIndex, 0)
|
|
}
|
|
}
|
|
|
|
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 final class RecordingTerminalSessionFactory: TerminalSessionFactoryType {
|
|
private(set) var requestedDirectories: [String?] = []
|
|
|
|
@MainActor
|
|
func makeSession(
|
|
fontSize: CGFloat,
|
|
theme: TerminalTheme,
|
|
shellPath: String,
|
|
initialDirectory: String?
|
|
) -> TerminalSession {
|
|
requestedDirectories.append(initialDirectory)
|
|
return TerminalSession(
|
|
fontSize: fontSize,
|
|
theme: theme,
|
|
shellPath: shellPath,
|
|
initialDirectory: initialDirectory,
|
|
startImmediately: false
|
|
)
|
|
}
|
|
}
|
|
|
|
private struct UnusedTerminalSessionFactory: TerminalSessionFactoryType {
|
|
@MainActor
|
|
func makeSession(
|
|
fontSize: CGFloat,
|
|
theme: TerminalTheme,
|
|
shellPath: String,
|
|
initialDirectory: String?
|
|
) -> TerminalSession {
|
|
fatalError("WorkspaceRegistryTests should not create live terminal sessions.")
|
|
}
|
|
}
|