import { render, screen, waitFor } from '@testing-library/react' import userEvent from '@testing-library/user-event' import { beforeEach, describe, expect, it, vi } from 'vitest' import BatchCommandDialog from '../../src/components/sessions/BatchCommandDialog' import type { Session } from '../../src/stores/sessionStore' import { mockDesktopApi } from '../setup' const sessions: Session[] = [ { id: 'host-a', name: 'Host A', host: '10.0.0.1', port: 22, username: 'root', authType: 'key' }, { id: 'host-b', name: 'Host B', host: '10.0.0.2', port: 2222, username: 'ops', authType: 'password' }, ] describe('BatchCommandDialog', () => { beforeEach(() => { vi.clearAllMocks() window.opsxApi = mockDesktopApi vi.mocked(mockDesktopApi.sessionGetById).mockImplementation(async (id) => ({ success: true, session: sessions.find((session) => session.id === id), })) vi.mocked(mockDesktopApi.sshConnect).mockImplementation(async (config) => ({ success: true, connectionId: `connection-${config.host}`, })) vi.mocked(mockDesktopApi.sshExec).mockImplementation(async (connectionId, command) => ({ success: true, result: `${connectionId}: ${command}`, })) }) it('executes the same command on every selected host and disconnects transient sessions', async () => { const user = userEvent.setup() render() await user.type(screen.getByLabelText('远程命令'), 'date') 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') expect(mockDesktopApi.sshExec).toHaveBeenCalledWith('connection-10.0.0.2', 'date') await waitFor(() => expect(mockDesktopApi.sshDisconnect).toHaveBeenCalledTimes(2)) expect(await screen.findByText('成功 2')).toBeVisible() 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( ) 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( ) const command = screen.getByLabelText('远程命令') await user.type(command, 'cat /etc/shadow') expect(command).toHaveValue('cat /etc/shadow') rerender() rerender() expect(screen.getByLabelText('远程命令')).toHaveValue('') }) })