-
-
Notifications
You must be signed in to change notification settings - Fork 2.4k
fix: restore terminal working directories on relaunch #2171
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
365306b
2e13c97
75c9424
1ad9017
0e26e5f
1852c3c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -41,6 +41,124 @@ final class SessionPersistenceTests: XCTestCase { | |
| XCTAssertEqual(restored.panelTitle(panelId: restoredPanelId), "Readme") | ||
| } | ||
|
|
||
| @MainActor | ||
| func testWorkspaceSessionSnapshotPersistsFocusedTerminalWorkingDirectory() throws { | ||
| let root = FileManager.default.temporaryDirectory | ||
| .appendingPathComponent("cmux-session-restore-cwd-\(UUID().uuidString)", isDirectory: true) | ||
| try FileManager.default.createDirectory(at: root, withIntermediateDirectories: true) | ||
| defer { try? FileManager.default.removeItem(at: root) } | ||
|
|
||
| let requestedDirectory = root.appendingPathComponent("requested", isDirectory: true) | ||
| let focusedDirectory = root.appendingPathComponent("focused", isDirectory: true) | ||
| let unfocusedDirectory = root.appendingPathComponent("unfocused", isDirectory: true) | ||
| try FileManager.default.createDirectory(at: requestedDirectory, withIntermediateDirectories: true) | ||
| try FileManager.default.createDirectory(at: focusedDirectory, withIntermediateDirectories: true) | ||
| try FileManager.default.createDirectory(at: unfocusedDirectory, withIntermediateDirectories: true) | ||
|
|
||
| let workspace = Workspace(title: "Terminal", workingDirectory: requestedDirectory.path, portOrdinal: 0) | ||
| let focusedPanelId = try XCTUnwrap(workspace.focusedPanelId) | ||
| workspace.updatePanelDirectory(panelId: focusedPanelId, directory: focusedDirectory.path) | ||
| let unfocusedPanel = try XCTUnwrap( | ||
| workspace.newTerminalSplit(from: focusedPanelId, orientation: .horizontal, focus: false) | ||
| ) | ||
| workspace.updatePanelDirectory(panelId: unfocusedPanel.id, directory: unfocusedDirectory.path) | ||
| workspace.focusPanel(focusedPanelId) | ||
|
|
||
| let snapshot = workspace.sessionSnapshot(includeScrollback: false) | ||
| let persistedFocusedPanel = try XCTUnwrap( | ||
| snapshot.panels.first(where: { $0.id == snapshot.focusedPanelId }) | ||
| ) | ||
| let persistedUnfocusedPanel = try XCTUnwrap( | ||
| snapshot.panels.first(where: { $0.id == unfocusedPanel.id }) | ||
| ) | ||
|
|
||
| XCTAssertEqual(persistedFocusedPanel.terminal?.workingDirectory, focusedDirectory.path) | ||
| XCTAssertEqual(persistedUnfocusedPanel.terminal?.workingDirectory, unfocusedDirectory.path) | ||
| XCTAssertEqual(snapshot.currentDirectory, focusedDirectory.path) | ||
| } | ||
|
|
||
| @MainActor | ||
| func testWorkspaceSessionSnapshotRestoresFocusedTerminalWorkingDirectoryWhenPanelDirectoryIsMissing() throws { | ||
| let root = FileManager.default.temporaryDirectory | ||
| .appendingPathComponent("cmux-session-restore-fallback-cwd-\(UUID().uuidString)", isDirectory: true) | ||
| try FileManager.default.createDirectory(at: root, withIntermediateDirectories: true) | ||
| defer { try? FileManager.default.removeItem(at: root) } | ||
|
|
||
| let requestedDirectory = root.appendingPathComponent("requested", isDirectory: true) | ||
| let restoredDirectory = root.appendingPathComponent("restored", isDirectory: true) | ||
| let explicitDirectory = root.appendingPathComponent("explicit", isDirectory: true) | ||
| try FileManager.default.createDirectory(at: requestedDirectory, withIntermediateDirectories: true) | ||
| try FileManager.default.createDirectory(at: restoredDirectory, withIntermediateDirectories: true) | ||
| try FileManager.default.createDirectory(at: explicitDirectory, withIntermediateDirectories: true) | ||
|
|
||
| var snapshot = makeSnapshot(version: SessionSnapshotSchema.currentVersion).windows[0].tabManager.workspaces[0] | ||
| let focusedPanelId = UUID() | ||
| let unfocusedPanelId = UUID() | ||
| snapshot.focusedPanelId = focusedPanelId | ||
| snapshot.currentDirectory = restoredDirectory.path | ||
| snapshot.layout = .pane( | ||
| SessionPaneLayoutSnapshot( | ||
| panelIds: [focusedPanelId, unfocusedPanelId], | ||
| selectedPanelId: focusedPanelId | ||
| ) | ||
| ) | ||
| snapshot.panels = [ | ||
| SessionPanelSnapshot( | ||
| id: focusedPanelId, | ||
| type: .terminal, | ||
| title: "Focused Terminal", | ||
| customTitle: nil, | ||
| directory: nil, | ||
| isPinned: false, | ||
| isManuallyUnread: false, | ||
| gitBranch: nil, | ||
| listeningPorts: [], | ||
| ttyName: nil, | ||
| terminal: SessionTerminalPanelSnapshot( | ||
| workingDirectory: nil, | ||
| scrollback: nil | ||
| ), | ||
| browser: nil, | ||
| markdown: nil | ||
| ), | ||
| SessionPanelSnapshot( | ||
| id: unfocusedPanelId, | ||
| type: .terminal, | ||
| title: "Unfocused Terminal", | ||
| customTitle: nil, | ||
| directory: explicitDirectory.path, | ||
| isPinned: false, | ||
| isManuallyUnread: false, | ||
| gitBranch: nil, | ||
| listeningPorts: [], | ||
| ttyName: nil, | ||
| terminal: SessionTerminalPanelSnapshot( | ||
| workingDirectory: nil, | ||
| scrollback: nil | ||
| ), | ||
| browser: nil, | ||
| markdown: nil | ||
| ) | ||
| ] | ||
|
|
||
| let restored = Workspace(title: "Terminal", workingDirectory: requestedDirectory.path, portOrdinal: 0) | ||
| restored.restoreSessionSnapshot(snapshot) | ||
|
|
||
| let restoredFocusedPanel = try XCTUnwrap(restored.terminalPanel(for: try XCTUnwrap(restored.focusedPanelId))) | ||
| let restoredUnfocusedPanel = try XCTUnwrap(restored.terminalPanel(for: unfocusedPanelId)) | ||
| XCTAssertEqual(restored.currentDirectory, restoredDirectory.path) | ||
| XCTAssertEqual( | ||
| restoredFocusedPanel.requestedWorkingDirectory, | ||
| restoredDirectory.path, | ||
| "Expected the focused restored terminal to use the workspace snapshot cwd when no panel-specific cwd was persisted" | ||
| ) | ||
| XCTAssertEqual( | ||
| restoredUnfocusedPanel.requestedWorkingDirectory, | ||
| explicitDirectory.path, | ||
| "Expected non-focused terminals to keep their own persisted directory instead of inheriting the workspace cwd" | ||
| ) | ||
| } | ||
|
Comment on lines
+87
to
+160
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
In let workingDirectory = snapshot.terminal?.workingDirectory ?? snapshot.directory ?? currentDirectoryWith both optional fields Either the test is covering the wrong scenario (it should simulate the case where |
||
|
|
||
| func testSaveAndLoadRoundTripWithCustomSnapshotPath() throws { | ||
| let tempDir = FileManager.default.temporaryDirectory | ||
| .appendingPathComponent("cmux-session-tests-\(UUID().uuidString)", isDirectory: true) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
restoreSessionSnapshotcreates new panel UUIDs and tracks old→new IDs internally, sounfocusedPanelIdfrom the snapshot is stale after restore. Looking uprestored.terminalPanel(for: unfocusedPanelId)will almost always returnnil, causing this regression test to fail before it validates the non-focused cwd behavior; the assertion should use a restored panel ID (for example via the restored layout/selection) instead of the pre-restore UUID.Useful? React with 👍 / 👎.