feat: add terminal broadcast, context menu, and shell close

Complete multi-pane broadcast, standard terminal right-click actions, batch host selection with progress, and native ssh_close_shell so closing a pane tears down the remote shell.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Logan.LiandCursor committed 2026-08-05 19:53:39 +08:00
1 parent 494ef6b9d0
commit 9ce71795b8
38 files changed
+1437 -186

No files matched your search

+38 -1
View File
@@ -33,7 +33,7 @@ describe('BatchCommandDialog', () => {
render(<BatchCommandDialog isOpen sessions={sessions} onClose={vi.fn()} />)
await user.type(screen.getByLabelText('远程命令'), 'date')
await user.click(screen.getByRole('button', { name: '执行命令' }))
await user.click(screen.getByRole('button', { name: '执行到 2 台' }))
await waitFor(() => expect(mockDesktopApi.sshExec).toHaveBeenCalledTimes(2))
expect(mockDesktopApi.sshExec).toHaveBeenCalledWith('connection-10.0.0.1', 'date')
@@ -43,4 +43,41 @@ describe('BatchCommandDialog', () => {
expect(screen.getByText('connection-10.0.0.1: date')).toBeVisible()
expect(screen.getByText('connection-10.0.0.2: date')).toBeVisible()
})
it('starts with the sidebar selection and lets the user adjust targets in the dialog', async () => {
const user = userEvent.setup()
render(
<BatchCommandDialog
isOpen
sessions={sessions}
initialSelectedIds={['host-a']}
onClose={vi.fn()}
/>
)
expect(screen.getByRole('checkbox', { name: /Host A/ })).toHaveAttribute('aria-checked', 'true')
expect(screen.getByRole('checkbox', { name: /Host B/ })).toHaveAttribute('aria-checked', 'false')
await user.click(screen.getByRole('checkbox', { name: /Host B/ }))
expect(screen.getByRole('button', { name: '执行到 2 台' })).toBeVisible()
await user.type(screen.getByLabelText('筛选主机'), '10.0.0.1')
expect(screen.getByRole('checkbox', { name: /Host A/ })).toBeVisible()
expect(screen.queryByRole('checkbox', { name: /Host B/ })).not.toBeInTheDocument()
})
it('clears the command when reopened so sensitive input is not retained', async () => {
const user = userEvent.setup()
const { rerender } = render(
<BatchCommandDialog isOpen sessions={sessions} onClose={vi.fn()} />
)
const command = screen.getByLabelText('远程命令')
await user.type(command, 'cat /etc/shadow')
expect(command).toHaveValue('cat /etc/shadow')
rerender(<BatchCommandDialog isOpen={false} sessions={sessions} onClose={vi.fn()} />)
rerender(<BatchCommandDialog isOpen sessions={sessions} onClose={vi.fn()} />)
expect(screen.getByLabelText('远程命令')).toHaveValue('')
})
})