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

320 lines
13 KiB
Swift

import XCTest
@testable import CommandNotch
@MainActor
final class ScreenRegistryTests: XCTestCase {
func testRefreshCreatesContextsForConnectedScreensUsingDefaultWorkspace() {
let workspaceRegistry = makeWorkspaceRegistry()
let settingsController = makeSettingsController()
let registry = ScreenRegistry(
workspaceRegistry: workspaceRegistry,
settingsController: settingsController,
connectedScreenIDsProvider: { ["screen-a", "screen-b"] },
activeScreenIDProvider: { "screen-b" },
screenLookup: { _ in nil }
)
XCTAssertEqual(registry.allScreens().map(\.id), ["screen-a", "screen-b"])
XCTAssertEqual(
registry.allScreens().map(\.workspaceID),
[workspaceRegistry.defaultWorkspaceID, workspaceRegistry.defaultWorkspaceID]
)
XCTAssertEqual(registry.activeScreenID(), "screen-b")
}
func testAssignWorkspaceUpdatesContextAndSurvivesReconnect() {
let workspaceRegistry = makeWorkspaceRegistry()
let settingsController = makeSettingsController()
var connectedScreenIDs = ["screen-a"]
let registry = ScreenRegistry(
workspaceRegistry: workspaceRegistry,
settingsController: settingsController,
connectedScreenIDsProvider: { connectedScreenIDs },
activeScreenIDProvider: { connectedScreenIDs.first },
screenLookup: { _ in nil }
)
let docsWorkspaceID = workspaceRegistry.createWorkspace(named: "Docs")
registry.assignWorkspace(docsWorkspaceID, to: "screen-a")
XCTAssertEqual(registry.screenContext(for: "screen-a")?.workspaceID, docsWorkspaceID)
connectedScreenIDs = []
registry.refreshConnectedScreens()
XCTAssertNil(registry.screenContext(for: "screen-a"))
connectedScreenIDs = ["screen-a"]
registry.refreshConnectedScreens()
XCTAssertEqual(registry.screenContext(for: "screen-a")?.workspaceID, docsWorkspaceID)
}
func testDeletedWorkspaceAssignmentFallsBackToDefaultWorkspace() {
let workspaceRegistry = makeWorkspaceRegistry()
let settingsController = makeSettingsController()
let assignmentStore = InMemoryScreenAssignmentStore()
let registry = ScreenRegistry(
workspaceRegistry: workspaceRegistry,
settingsController: settingsController,
assignmentStore: assignmentStore,
connectedScreenIDsProvider: { ["screen-a"] },
activeScreenIDProvider: { "screen-a" },
screenLookup: { _ in nil }
)
let reviewWorkspaceID = workspaceRegistry.createWorkspace(named: "Review")
registry.assignWorkspace(reviewWorkspaceID, to: "screen-a")
workspaceRegistry.deleteWorkspace(id: reviewWorkspaceID)
registry.refreshConnectedScreens()
XCTAssertEqual(
registry.screenContext(for: "screen-a")?.workspaceID,
workspaceRegistry.defaultWorkspaceID
)
XCTAssertEqual(
assignmentStore.savedAssignments["screen-a"],
workspaceRegistry.defaultWorkspaceID
)
}
func testRegistryLoadsPersistedAssignmentsFromStore() {
let workspaceRegistry = makeWorkspaceRegistry()
let settingsController = makeSettingsController()
let docsWorkspaceID = workspaceRegistry.createWorkspace(named: "Docs")
let assignmentStore = InMemoryScreenAssignmentStore()
assignmentStore.savedAssignments = ["screen-a": docsWorkspaceID]
let registry = ScreenRegistry(
workspaceRegistry: workspaceRegistry,
settingsController: settingsController,
assignmentStore: assignmentStore,
connectedScreenIDsProvider: { ["screen-a"] },
activeScreenIDProvider: { "screen-a" },
screenLookup: { _ in nil }
)
XCTAssertEqual(registry.screenContext(for: "screen-a")?.workspaceID, docsWorkspaceID)
}
func testAssignWorkspacePersistsAssignments() {
let workspaceRegistry = makeWorkspaceRegistry()
let settingsController = makeSettingsController()
let assignmentStore = InMemoryScreenAssignmentStore()
let registry = ScreenRegistry(
workspaceRegistry: workspaceRegistry,
settingsController: settingsController,
assignmentStore: assignmentStore,
connectedScreenIDsProvider: { ["screen-a"] },
activeScreenIDProvider: { "screen-a" },
screenLookup: { _ in nil }
)
let reviewWorkspaceID = workspaceRegistry.createWorkspace(named: "Review")
registry.assignWorkspace(reviewWorkspaceID, to: "screen-a")
XCTAssertEqual(assignmentStore.savedAssignments["screen-a"], reviewWorkspaceID)
}
func testWorkspaceControllerTracksAssignedWorkspace() {
let workspaceRegistry = makeWorkspaceRegistry()
let settingsController = makeSettingsController()
let registry = ScreenRegistry(
workspaceRegistry: workspaceRegistry,
settingsController: settingsController,
connectedScreenIDsProvider: { ["screen-a"] },
activeScreenIDProvider: { "screen-a" },
screenLookup: { _ in nil }
)
let docsWorkspaceID = workspaceRegistry.createWorkspace(named: "Docs")
XCTAssertEqual(registry.workspaceController(for: "screen-a").id, workspaceRegistry.defaultWorkspaceID)
registry.assignWorkspace(docsWorkspaceID, to: "screen-a")
XCTAssertEqual(registry.workspaceController(for: "screen-a").id, docsWorkspaceID)
}
func testDeleteWorkspaceReassignsConnectedAndPersistedScreensToFallback() {
let workspaceRegistry = makeWorkspaceRegistry()
let settingsController = makeSettingsController()
let docsWorkspaceID = workspaceRegistry.createWorkspace(named: "Docs")
let reviewWorkspaceID = workspaceRegistry.createWorkspace(named: "Review")
let assignmentStore = InMemoryScreenAssignmentStore()
assignmentStore.savedAssignments = ["screen-a": docsWorkspaceID, "screen-b": docsWorkspaceID]
let registry = ScreenRegistry(
workspaceRegistry: workspaceRegistry,
settingsController: settingsController,
assignmentStore: assignmentStore,
connectedScreenIDsProvider: { ["screen-a"] },
activeScreenIDProvider: { "screen-a" },
screenLookup: { _ in nil }
)
registry.assignWorkspace(docsWorkspaceID, to: "screen-a")
let fallbackWorkspaceID = registry.deleteWorkspace(
docsWorkspaceID,
preferredFallback: reviewWorkspaceID
)
XCTAssertEqual(fallbackWorkspaceID, reviewWorkspaceID)
XCTAssertEqual(registry.screenContext(for: "screen-a")?.workspaceID, reviewWorkspaceID)
XCTAssertEqual(assignmentStore.savedAssignments["screen-a"], reviewWorkspaceID)
XCTAssertEqual(assignmentStore.savedAssignments["screen-b"], reviewWorkspaceID)
}
func testAssignedScreenCountIncludesDisconnectedAssignments() {
let workspaceRegistry = makeWorkspaceRegistry()
let settingsController = makeSettingsController()
let docsWorkspaceID = workspaceRegistry.createWorkspace(named: "Docs")
let assignmentStore = InMemoryScreenAssignmentStore()
assignmentStore.savedAssignments = ["screen-a": docsWorkspaceID, "screen-b": docsWorkspaceID]
let registry = ScreenRegistry(
workspaceRegistry: workspaceRegistry,
settingsController: settingsController,
assignmentStore: assignmentStore,
connectedScreenIDsProvider: { ["screen-a"] },
activeScreenIDProvider: { "screen-a" },
screenLookup: { _ in nil }
)
XCTAssertEqual(registry.assignedScreenCount(to: docsWorkspaceID), 2)
XCTAssertEqual(registry.assignedScreenIDs(to: docsWorkspaceID), ["screen-a", "screen-b"])
}
func testClaimWorkspacePresentationTracksPresenterPerWorkspace() {
let workspaceRegistry = makeWorkspaceRegistry()
let settingsController = makeSettingsController()
let docsWorkspaceID = workspaceRegistry.createWorkspace(named: "Docs")
let registry = ScreenRegistry(
workspaceRegistry: workspaceRegistry,
settingsController: settingsController,
connectedScreenIDsProvider: { ["screen-a", "screen-b"] },
activeScreenIDProvider: { "screen-a" },
screenLookup: { _ in nil }
)
registry.assignWorkspace(docsWorkspaceID, to: "screen-a")
registry.assignWorkspace(docsWorkspaceID, to: "screen-b")
XCTAssertNil(registry.claimWorkspacePresentation(for: "screen-a"))
XCTAssertEqual(registry.presentingScreenID(for: docsWorkspaceID), "screen-a")
XCTAssertEqual(registry.claimWorkspacePresentation(for: "screen-b"), "screen-a")
XCTAssertEqual(registry.presentingScreenID(for: docsWorkspaceID), "screen-b")
registry.releaseWorkspacePresentation(for: "screen-b")
XCTAssertNil(registry.presentingScreenID(for: docsWorkspaceID))
}
func testAssignWorkspaceReleasesPreviousPresentationOwnership() {
let workspaceRegistry = makeWorkspaceRegistry()
let settingsController = makeSettingsController()
let docsWorkspaceID = workspaceRegistry.createWorkspace(named: "Docs")
let reviewWorkspaceID = workspaceRegistry.createWorkspace(named: "Review")
let registry = ScreenRegistry(
workspaceRegistry: workspaceRegistry,
settingsController: settingsController,
connectedScreenIDsProvider: { ["screen-a"] },
activeScreenIDProvider: { "screen-a" },
screenLookup: { _ in nil }
)
registry.assignWorkspace(docsWorkspaceID, to: "screen-a")
_ = registry.claimWorkspacePresentation(for: "screen-a")
XCTAssertEqual(registry.presentingScreenID(for: docsWorkspaceID), "screen-a")
registry.assignWorkspace(reviewWorkspaceID, to: "screen-a")
XCTAssertNil(registry.presentingScreenID(for: docsWorkspaceID))
XCTAssertEqual(registry.screenContext(for: "screen-a")?.workspaceID, reviewWorkspaceID)
}
func testConnectedScreenSummariesReflectActiveScreenAndAssignments() {
let workspaceRegistry = makeWorkspaceRegistry()
let settingsController = makeSettingsController()
let docsWorkspaceID = workspaceRegistry.createWorkspace(named: "Docs")
let registry = ScreenRegistry(
workspaceRegistry: workspaceRegistry,
settingsController: settingsController,
connectedScreenIDsProvider: { ["screen-a", "screen-b"] },
activeScreenIDProvider: { "screen-b" },
screenLookup: { _ in nil }
)
registry.assignWorkspace(docsWorkspaceID, to: "screen-a")
XCTAssertEqual(
registry.connectedScreenSummaries(),
[
ConnectedScreenSummary(
id: "screen-a",
displayName: "Screen 1",
isActive: false,
assignedWorkspaceID: docsWorkspaceID
),
ConnectedScreenSummary(
id: "screen-b",
displayName: "Screen 2",
isActive: true,
assignedWorkspaceID: workspaceRegistry.defaultWorkspaceID
)
]
)
}
private func makeWorkspaceRegistry() -> WorkspaceRegistry {
let settingsProvider = ScreenRegistryTestSettingsProvider()
let sessionFactory = ScreenRegistryUnusedTerminalSessionFactory()
return WorkspaceRegistry(
initialWorkspaces: [],
controllerFactory: { summary in
WorkspaceController(
summary: summary,
sessionFactory: sessionFactory,
settingsProvider: settingsProvider,
bootstrapDefaultTab: false
)
}
)
}
private func makeSettingsController() -> AppSettingsController {
AppSettingsController(store: TestAppSettingsStore())
}
}
private final class InMemoryScreenAssignmentStore: ScreenAssignmentStoreType {
var savedAssignments: [ScreenID: WorkspaceID] = [:]
func loadScreenAssignments() -> [ScreenID: WorkspaceID] {
savedAssignments
}
func saveScreenAssignments(_ assignments: [ScreenID: WorkspaceID]) {
savedAssignments = assignments
}
}
private final class TestAppSettingsStore: AppSettingsStoreType {
private var storedSettings = AppSettings.default
func load() -> AppSettings {
storedSettings
}
func save(_ settings: AppSettings) {
storedSettings = settings
}
}
private final class ScreenRegistryTestSettingsProvider: TerminalSessionConfigurationProviding {
let terminalSessionConfiguration = TerminalSessionConfiguration(fontSize: 13, theme: .terminalApp, shellPath: "")
let hotkeySettings = AppSettings.default.hotkeys
let terminalSizePresets = TerminalSizePresetStore.loadDefaults()
}
private struct ScreenRegistryUnusedTerminalSessionFactory: TerminalSessionFactoryType {
@MainActor
func makeSession(fontSize: CGFloat, theme: TerminalTheme, shellPath: String) -> TerminalSession {
fatalError("ScreenRegistryTests should not create live terminal sessions.")
}
}