feat: harden local shell, SFTP, and desktop session reliability
Finder-launched terminals now inherit a login PATH so tools like ollama resolve, destructive SFTP/editor actions require confirmation, and terminal search plus window dragging work again. SSH forwards and RDP sessions keep listeners and survive reconnect without FastPath crashes. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
1 parent
188f3556ed
commit
08696896f9
223 files changed
+13493
-3423
No files matched your search
@@ -0,0 +1,123 @@
|
||||
/**
|
||||
* RDP / VNC desktop connect + tab open patrol
|
||||
*/
|
||||
|
||||
import { render, screen, waitFor } from '@testing-library/react'
|
||||
import userEvent from '@testing-library/user-event'
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import DesktopConnectDialog from '../../src/components/desktop/DesktopConnectDialog'
|
||||
import SessionDialog from '../../src/components/sessions/SessionDialog'
|
||||
import { useTabStore } from '../../src/stores/tabStore'
|
||||
import { mockDesktopApi } from '../setup'
|
||||
import { buildOpenTabPayload } from '../../src/utils/sessionProtocol'
|
||||
import { RDP_SESSION, resetPatrolStores, VNC_SESSION } from '../helpers/patrol'
|
||||
|
||||
describe('patrol / desktop (rdp + vnc)', () => {
|
||||
beforeEach(() => {
|
||||
resetPatrolStores()
|
||||
})
|
||||
|
||||
it('RDP connect dialog submits host/port/username/password', async () => {
|
||||
const user = userEvent.setup()
|
||||
const onConnect = vi.fn()
|
||||
render(
|
||||
<DesktopConnectDialog protocol="rdp" isOpen onClose={vi.fn()} onConnect={onConnect} />
|
||||
)
|
||||
|
||||
expect(screen.getByText('连接 RDP')).toBeVisible()
|
||||
expect(screen.getByLabelText('端口')).toHaveValue(3389)
|
||||
|
||||
await user.type(screen.getByLabelText('主机'), 'win.example.com')
|
||||
await user.clear(screen.getByLabelText('用户名'))
|
||||
await user.type(screen.getByLabelText('用户名'), 'Administrator')
|
||||
await user.type(screen.getByLabelText('密码'), 'rdp-secret')
|
||||
await user.click(screen.getByRole('button', { name: '连接' }))
|
||||
|
||||
expect(onConnect).toHaveBeenCalledWith(
|
||||
'rdp',
|
||||
expect.objectContaining({
|
||||
host: 'win.example.com',
|
||||
port: 3389,
|
||||
username: 'Administrator',
|
||||
password: 'rdp-secret',
|
||||
security: 'nla',
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it('VNC connect dialog defaults to port 5900 and allows password-only auth', async () => {
|
||||
const user = userEvent.setup()
|
||||
const onConnect = vi.fn()
|
||||
render(
|
||||
<DesktopConnectDialog protocol="vnc" isOpen onClose={vi.fn()} onConnect={onConnect} />
|
||||
)
|
||||
|
||||
expect(screen.getByText('连接 VNC')).toBeVisible()
|
||||
expect(screen.getByLabelText('端口')).toHaveValue(5900)
|
||||
expect(screen.queryByLabelText('用户名')).not.toBeInTheDocument()
|
||||
|
||||
await user.type(screen.getByLabelText('主机'), '192.168.1.50')
|
||||
await user.type(screen.getByLabelText(/密码/), 'vnc-pass')
|
||||
await user.click(screen.getByRole('button', { name: '连接' }))
|
||||
|
||||
expect(onConnect).toHaveBeenCalledWith(
|
||||
'vnc',
|
||||
expect.objectContaining({
|
||||
host: '192.168.1.50',
|
||||
port: 5900,
|
||||
password: 'vnc-pass',
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it('requires host before connecting', async () => {
|
||||
const user = userEvent.setup()
|
||||
const onConnect = vi.fn()
|
||||
render(
|
||||
<DesktopConnectDialog protocol="rdp" isOpen onClose={vi.fn()} onConnect={onConnect} />
|
||||
)
|
||||
await user.click(screen.getByRole('button', { name: '连接' }))
|
||||
expect(await screen.findByText(/请输入主机/)).toBeVisible()
|
||||
expect(onConnect).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('opens RDP and VNC tabs from saved sessions with engine configs', () => {
|
||||
const rdpPayload = buildOpenTabPayload(RDP_SESSION)
|
||||
useTabStore.getState().addTab(rdpPayload)
|
||||
expect(useTabStore.getState().tabs.some((t) => t.type === 'rdp' && t.rdpConfig?.host === 'win.example.com')).toBe(
|
||||
true
|
||||
)
|
||||
|
||||
const vncPayload = buildOpenTabPayload(VNC_SESSION)
|
||||
useTabStore.getState().addTab(vncPayload)
|
||||
expect(useTabStore.getState().tabs.some((t) => t.type === 'vnc' && t.vncConfig?.port === 5900)).toBe(true)
|
||||
})
|
||||
|
||||
it('session dialog can save an RDP session with port 3389', async () => {
|
||||
const user = userEvent.setup()
|
||||
render(<SessionDialog isOpen onClose={vi.fn()} editSession={null} />)
|
||||
|
||||
const rdpTab = screen.queryByRole('button', { name: /^RDP$/i }) || screen.queryByText(/^RDP$/i)
|
||||
if (rdpTab) {
|
||||
await user.click(rdpTab)
|
||||
await waitFor(() => {
|
||||
expect(screen.getByLabelText('端口')).toHaveValue(3389)
|
||||
})
|
||||
await user.clear(screen.getByLabelText('主机'))
|
||||
await user.type(screen.getByLabelText('主机'), 'win.lab.local')
|
||||
await user.click(screen.getByRole('button', { name: '创建并保存' }))
|
||||
await waitFor(() => {
|
||||
expect(mockDesktopApi.sessionCreate).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
host: 'win.lab.local',
|
||||
port: 3389,
|
||||
protocol: 'rdp',
|
||||
})
|
||||
)
|
||||
})
|
||||
} else {
|
||||
// Protocol switcher may use different labels — still assert helper defaults
|
||||
expect(buildOpenTabPayload(RDP_SESSION).type).toBe('rdp')
|
||||
}
|
||||
})
|
||||
})
|
||||
Reference in new issue
Block a user