/** * 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() 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() 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() 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() 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) }) expect(screen.getAllByLabelText('密码')).toHaveLength(1) await user.click(screen.getByText('高级选项')) expect(screen.queryByLabelText('跳板机(可选)')).not.toBeInTheDocument() expect(screen.queryByLabelText('启动命令(可选)')).not.toBeInTheDocument() 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') } }) })