import { describe, it, expect, vi, beforeEach } from 'vitest'; import { render, screen, fireEvent, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import OrderManagement from '../../src/components/OrderManagement'; import { orderClientManager } from '../../src/api/orderClient'; import { OrderStatus, WorkStatus } from '@d8d/allin-enums'; import { completeRadixSelectFlow } from '@d8d/shared-ui-components/tests/utils'; // Mock 薪资客户端 vi.mock('@d8d/allin-salary-management-ui', () => ({ salaryClientManager: { get: vi.fn(() => ({ byProvinceCity: { $get: vi.fn(({ query }) => { // 模拟API响应 const { provinceId } = query; // 根据省份ID返回不同的薪资 let salary = 5000; // 默认 if (provinceId === 1 || provinceId === 2 || provinceId === 3 || provinceId === 4) { salary = 8000; // 一线城市 } else if (provinceId === 5 || provinceId === 6 || provinceId === 7) { salary = 6000; // 二线城市 } return Promise.resolve({ ok: true, json: () => Promise.resolve({ salary }) }); }) } })) } })); // Mock 区域选择器组件 vi.mock('@d8d/area-management-ui', () => ({ AreaSelect: vi.fn(({ value, onChange }) => { return (
); }) })); // Mock 文件选择器组件 vi.mock('@d8d/file-management-ui', () => ({ FileSelector: vi.fn(({ value, onChange }) => { return (
{ if (onChange && e.target.files?.[0]) { onChange('mock-file-id-123'); } }} /> {value &&
已选择文件: {value}
}
); }) })); // Mock 共享工具包中的rpcClient函数 vi.mock('@d8d/shared-ui-components/utils/hc', () => ({ rpcClient: vi.fn(() => { // 返回一个模拟的RPC客户端 const mockClient = { getAllPlatforms: { $get: vi.fn(() => Promise.resolve({ status: 200, json: async () => ({ data: [ { id: 1, name: '平台1' }, { id: 2, name: '平台2' }, { id: 3, name: '平台3' } ], total: 3 }) })) }, getAllCompanies: { $get: vi.fn(() => Promise.resolve({ status: 200, json: async () => ({ data: [ { id: 1, name: '公司1' }, { id: 2, name: '公司2' }, { id: 3, name: '公司3' } ], total: 3 }) })) }, getAllChannels: { $get: vi.fn(() => Promise.resolve({ status: 200, json: async () => ({ data: [ { id: 1, name: '渠道1' }, { id: 2, name: '渠道2' }, { id: 3, name: '渠道3' } ], total: 3 }) })) }, // 残疾人API - 用于残疾人选择器组件 searchDisabledPersons: { $get: vi.fn(() => Promise.resolve({ status: 200, json: async () => ({ data: [ { id: 1, name: '测试残疾人', gender: '男', idCard: '110101199001011234', // 添加身份证号字段 disabilityId: 'D123456', disabilityType: '肢体残疾', disabilityLevel: '三级', phone: '13800138000', province: '北京', city: '北京市', provinceId: 1, cityId: 2, isInBlackList: 0 } ], total: 1, page: 1, pageSize: 10 }) })) }, getAllDisabledPersons: { $get: vi.fn(() => Promise.resolve({ status: 200, json: async () => ({ data: [ { id: 1, name: '测试残疾人', gender: '男', idCard: '110101199001011234', // 添加身份证号字段 disabilityId: 'D123456', disabilityType: '肢体残疾', disabilityLevel: '三级', phone: '13800138000', province: '北京', city: '北京市', provinceId: 1, cityId: 2, isInBlackList: 0 } ], total: 1, page: 1, pageSize: 10 }) })) } }; return mockClient; }) })); // 完整的mock响应对象 const createMockResponse = (status: number, data?: any) => ({ status, ok: status >= 200 && status < 300, body: null, bodyUsed: false, statusText: status === 200 ? 'OK' : status === 201 ? 'Created' : status === 204 ? 'No Content' : 'Error', headers: new Headers(), url: '', redirected: false, type: 'basic' as ResponseType, json: async () => data || {}, text: async () => '', blob: async () => new Blob(), arrayBuffer: async () => new ArrayBuffer(0), formData: async () => new FormData(), clone: function() { return this; } }); // Mock API client vi.mock('../../src/api/orderClient', () => { const mockOrderClient = { list: { $get: vi.fn(() => Promise.resolve(createMockResponse(200, { data: [ { id: 1, orderName: '测试订单1', platformId: 1, companyId: 1, channelId: 1, expectedStartDate: '2024-01-01T00:00:00Z', expectedEndDate: '2024-12-31T00:00:00Z', orderStatus: OrderStatus.DRAFT, workStatus: WorkStatus.NOT_WORKING, provinceId: 1, cityId: 2, districtId: 3, address: '测试地址', contactPerson: '张三', contactPhone: '13800138001', remark: '测试备注', createTime: '2024-01-01T00:00:00Z', updateTime: '2024-01-01T00:00:00Z' }, { id: 2, orderName: '测试订单2', platformId: 2, companyId: 2, channelId: 2, expectedStartDate: '2024-02-01T00:00:00Z', expectedEndDate: '2024-12-31T00:00:00Z', orderStatus: OrderStatus.CONFIRMED, workStatus: WorkStatus.PRE_WORKING, provinceId: 4, cityId: 5, districtId: 6, address: '测试地址2', contactPerson: '李四', contactPhone: '13800138002', remark: '测试备注2', createTime: '2024-02-01T00:00:00Z', updateTime: '2024-02-01T00:00:00Z' } ], total: 2 }))), }, create: { $post: vi.fn(() => Promise.resolve(createMockResponse(200, { id: 3, orderName: '新订单', platformId: 3, companyId: 3, channelId: 3, expectedStartDate: '2024-03-01T00:00:00Z', expectedEndDate: '2024-12-31T00:00:00Z', orderStatus: OrderStatus.DRAFT, workStatus: WorkStatus.NOT_WORKING, provinceId: 7, cityId: 8, districtId: 9, address: '新地址', contactPerson: '王五', contactPhone: '13800138003', remark: '新备注', createTime: '2024-03-01T00:00:00Z', updateTime: '2024-03-01T00:00:00Z' }))), }, update: { ':id': { $put: vi.fn(() => Promise.resolve(createMockResponse(200, { id: 1, orderName: '更新后的订单', platformId: 1, companyId: 1, channelId: 1, expectedStartDate: '2024-01-01T00:00:00Z', expectedEndDate: '2024-12-31T00:00:00Z', orderStatus: OrderStatus.CONFIRMED, workStatus: WorkStatus.PRE_WORKING, provinceId: 1, cityId: 2, districtId: 3, address: '更新后的地址', contactPerson: '张三', contactPhone: '13800138001', remark: '更新后的备注', createTime: '2024-01-01T00:00:00Z', updateTime: '2024-03-01T00:00:00Z' }))), }, }, delete: { ':id': { $delete: vi.fn(() => Promise.resolve(createMockResponse(200, { success: true }))), }, }, detail: { ':id': { $get: vi.fn(() => Promise.resolve(createMockResponse(200, { id: 1, orderName: '测试订单1', platformId: 1, companyId: 1, channelId: 1, expectedStartDate: '2024-01-01T00:00:00Z', actualStartDate: null, actualEndDate: null, orderStatus: OrderStatus.DRAFT, workStatus: WorkStatus.NOT_WORKING, provinceId: 1, cityId: 2, districtId: 3, address: '测试地址', contactPerson: '张三', contactPhone: '13800138001', remark: '测试备注', createTime: '2024-01-01T00:00:00Z', updateTime: '2024-01-01T00:00:00Z', orderPersons: [ { id: 1, orderId: 1, personId: 100, // 改为不同的ID,避免与测试选择的人员冲突 joinDate: '2024-01-01', workStatus: 1, salaryDetail: 5000, person: { id: 100, name: '测试人员100', gender: '男', disabilityType: '视力残疾', phone: '13800138000' } } ] }))), }, }, activate: { ':orderId': { $post: vi.fn(() => Promise.resolve(createMockResponse(200, { success: true }))), }, }, close: { ':orderId': { $post: vi.fn(() => Promise.resolve(createMockResponse(200, { success: true }))), }, }, ':orderId': { persons: { batch: { $post: vi.fn(() => Promise.resolve(createMockResponse(200, { success: true, message: '批量添加人员成功', addedCount: 2 }))), }, }, }, assets: { create: { $post: vi.fn(() => Promise.resolve(createMockResponse(200, { id: 1, orderId: 1, personId: 1, assetType: 'ID_CARD', assetFileType: 'IMAGE', fileId: 1, relatedTime: '2024-01-01T00:00:00Z', createTime: '2024-01-01T00:00:00Z', updateTime: '2024-01-01T00:00:00Z' }))), }, query: { $get: vi.fn(() => Promise.resolve(createMockResponse(200, { data: [], total: 0 }))), }, delete: { ':id': { $delete: vi.fn(() => Promise.resolve(createMockResponse(200, { success: true, message: '删除成功' }))), }, }, }, }; const mockOrderClientManager = { getInstance: vi.fn(() => ({ get: vi.fn(() => mockOrderClient), reset: vi.fn(), })), get: vi.fn(() => mockOrderClient), reset: vi.fn(), }; return { orderClientManager: mockOrderClientManager, orderClient: mockOrderClient, }; }); // Mock toast vi.mock('sonner', () => ({ toast: { success: vi.fn(), error: vi.fn(), }, })); describe('订单管理集成测试', () => { let queryClient: QueryClient; beforeEach(() => { queryClient = new QueryClient({ defaultOptions: { queries: { retry: false, }, }, }); vi.clearAllMocks(); }); const renderOrderManagement = () => { return render( ); }; describe('CRUD流程测试', () => { it('应该成功加载订单列表', async () => { renderOrderManagement(); // 等待数据加载 await waitFor(() => { expect(screen.getByText('测试订单1')).toBeInTheDocument(); expect(screen.getByText('测试订单2')).toBeInTheDocument(); }); // 验证表格渲染 expect(screen.getByTestId('order-row-1')).toBeInTheDocument(); expect(screen.getByTestId('order-row-2')).toBeInTheDocument(); // 验证状态徽章 expect(screen.getByText('草稿')).toBeInTheDocument(); expect(screen.getByText('已确认')).toBeInTheDocument(); expect(screen.getByText('未就业')).toBeInTheDocument(); expect(screen.getByText('待就业')).toBeInTheDocument(); }); it('应该成功创建订单', async () => { renderOrderManagement(); // 点击创建订单按钮 const createButton = screen.getByTestId('create-order-button'); fireEvent.click(createButton); // 验证订单表单模态框打开 await waitFor(() => { expect(screen.getByTestId('create-order-dialog-title')).toBeInTheDocument(); }); // 这里可以添加表单填写和提交的测试 // 由于表单组件比较复杂,这里只验证模态框能正常打开 }); it('应该成功编辑订单', async () => { renderOrderManagement(); // 等待数据加载 await waitFor(() => { expect(screen.getByTestId('order-row-1')).toBeInTheDocument(); }); // 先点击下拉菜单触发器,然后点击编辑按钮 const menuTrigger = screen.getByTestId('order-menu-trigger-1'); expect(menuTrigger).toBeInTheDocument(); // 使用userEvent.click代替fireEvent.click,更好地模拟用户交互 await userEvent.click(menuTrigger); // 等待下拉菜单打开,然后点击编辑按钮 await waitFor(() => { // 检查下拉菜单内容是否渲染 - 使用更精确的选择器 // 下拉菜单中的"操作"是DropdownMenuLabel,而表格中的"操作"是表头 // 我们可以检查下拉菜单中的特定元素 const editButton = screen.getByTestId('edit-order-button-1'); expect(editButton).toBeInTheDocument(); }); const editButton = screen.getByTestId('edit-order-button-1'); await userEvent.click(editButton); // 验证编辑表单模态框打开 await waitFor(() => { expect(screen.getByText('编辑订单')).toBeInTheDocument(); }); }); it('应该成功删除订单', async () => { renderOrderManagement(); // 等待数据加载 await waitFor(() => { expect(screen.getByTestId('order-row-1')).toBeInTheDocument(); }); // 先点击下拉菜单触发器,然后点击删除按钮 const menuTrigger = screen.getByTestId('order-menu-trigger-1'); expect(menuTrigger).toBeInTheDocument(); await userEvent.click(menuTrigger); // 等待下拉菜单打开,然后点击删除按钮 await waitFor(() => { const deleteButton = screen.getByTestId('delete-order-button-1'); expect(deleteButton).toBeInTheDocument(); }); const deleteButton = screen.getByTestId('delete-order-button-1'); await userEvent.click(deleteButton); // 验证删除确认对话框显示 await waitFor(() => { expect(screen.getByTestId('delete-confirm-dialog')).toBeInTheDocument(); expect(screen.getByTestId('delete-confirm-dialog-title')).toHaveTextContent('删除订单'); expect(screen.getByTestId('delete-confirm-dialog-description')).toHaveTextContent('确定要删除这个订单吗?此操作不可撤销。'); }); // 点击确认按钮 const confirmButton = screen.getByTestId('delete-confirm-dialog-confirm'); await userEvent.click(confirmButton); // 验证API调用 await waitFor(() => { expect(orderClientManager.get().delete[':id'].$delete).toHaveBeenCalledWith({ param: { id: 1 }, }); }); }); it('应该成功激活订单', async () => { renderOrderManagement(); // 等待数据加载 await waitFor(() => { expect(screen.getByTestId('order-row-1')).toBeInTheDocument(); }); // 先打开下拉菜单,然后点击激活按钮(只有草稿状态的订单才有激活按钮) const menuTrigger = screen.getByTestId('order-menu-trigger-1'); expect(menuTrigger).toBeInTheDocument(); await userEvent.click(menuTrigger); // 等待下拉菜单打开,然后点击激活按钮 await waitFor(() => { const activateButton = screen.getByTestId('activate-order-button-1'); expect(activateButton).toBeInTheDocument(); }); const activateButton = screen.getByTestId('activate-order-button-1'); await userEvent.click(activateButton); // 验证激活确认对话框显示 await waitFor(() => { expect(screen.getByTestId('activate-confirm-dialog')).toBeInTheDocument(); expect(screen.getByTestId('activate-confirm-dialog-title')).toHaveTextContent('激活订单'); expect(screen.getByTestId('activate-confirm-dialog-description')).toHaveTextContent('确定要激活这个订单吗?订单激活后将进入进行中状态。'); }); // 点击确认按钮 const confirmButton = screen.getByTestId('activate-confirm-dialog-confirm'); await userEvent.click(confirmButton); // 验证API调用 await waitFor(() => { expect(orderClientManager.get().activate[':orderId'].$post).toHaveBeenCalledWith({ param: { orderId: 1 }, }); }); }); it('应该成功关闭订单', async () => { renderOrderManagement(); // 等待数据加载 await waitFor(() => { expect(screen.getByTestId('order-row-2')).toBeInTheDocument(); }); // 先打开下拉菜单,然后点击关闭按钮(只有已确认或进行中的订单有关闭按钮) const menuTrigger = screen.getByTestId('order-menu-trigger-2'); expect(menuTrigger).toBeInTheDocument(); await userEvent.click(menuTrigger); // 等待下拉菜单打开,然后点击关闭按钮 await waitFor(() => { const closeButton = screen.getByTestId('close-order-button-2'); expect(closeButton).toBeInTheDocument(); }); const closeButton = screen.getByTestId('close-order-button-2'); await userEvent.click(closeButton); // 验证关闭确认对话框显示 await waitFor(() => { expect(screen.getByTestId('close-confirm-dialog')).toBeInTheDocument(); expect(screen.getByTestId('close-confirm-dialog-title')).toHaveTextContent('关闭订单'); expect(screen.getByTestId('close-confirm-dialog-description')).toHaveTextContent('确定要关闭这个订单吗?订单关闭后将无法再添加人员或附件。'); }); // 点击确认按钮 const confirmButton = screen.getByTestId('close-confirm-dialog-confirm'); await userEvent.click(confirmButton); // 验证API调用 await waitFor(() => { expect(orderClientManager.get().close[':orderId'].$post).toHaveBeenCalledWith({ param: { orderId: 2 }, }); }); }); it('应该可以取消删除操作', async () => { renderOrderManagement(); // 等待数据加载 await waitFor(() => { expect(screen.getByTestId('order-row-1')).toBeInTheDocument(); }); // 先点击下拉菜单触发器,然后点击删除按钮 const menuTrigger = screen.getByTestId('order-menu-trigger-1'); expect(menuTrigger).toBeInTheDocument(); await userEvent.click(menuTrigger); // 等待下拉菜单打开,然后点击删除按钮 await waitFor(() => { const deleteButton = screen.getByTestId('delete-order-button-1'); expect(deleteButton).toBeInTheDocument(); }); const deleteButton = screen.getByTestId('delete-order-button-1'); await userEvent.click(deleteButton); // 验证删除确认对话框显示 await waitFor(() => { expect(screen.getByTestId('delete-confirm-dialog')).toBeInTheDocument(); }); // 点击取消按钮 const cancelButton = screen.getByTestId('delete-confirm-dialog-cancel'); await userEvent.click(cancelButton); // 验证对话框关闭 await waitFor(() => { expect(screen.queryByTestId('delete-confirm-dialog')).not.toBeInTheDocument(); }); // 验证API没有被调用 expect(orderClientManager.get().delete[':id'].$delete).not.toHaveBeenCalled(); }); }); describe('文件上传集成测试', () => { it('应该成功打开资产关联模态框', async () => { renderOrderManagement(); // 等待数据加载 await waitFor(() => { expect(screen.getByTestId('order-row-1')).toBeInTheDocument(); }); // 先打开下拉菜单,然后点击添加附件按钮 const menuTrigger = screen.getByTestId('order-menu-trigger-1'); expect(menuTrigger).toBeInTheDocument(); await userEvent.click(menuTrigger); // 等待下拉菜单打开,然后点击添加附件按钮 await waitFor(() => { const addAssetButton = screen.getByTestId('add-asset-button-1'); expect(addAssetButton).toBeInTheDocument(); }); const addAssetButton = screen.getByTestId('add-asset-button-1'); await userEvent.click(addAssetButton); // 验证资产关联模态框打开 await waitFor(() => { expect(screen.getByTestId('order-asset-modal-title')).toBeInTheDocument(); }); // 验证文件选择器组件存在 - 可能需要在表单中才会显示 // 先验证模态框基本结构 expect(screen.getByTestId('order-asset-modal-title')).toBeInTheDocument(); // 文件选择器可能在选择了残疾人才显示,这里先跳过具体验证 }); }); describe('区域选择器集成测试', () => { it('应该成功打开订单表单并显示区域选择器', async () => { renderOrderManagement(); // 点击创建订单按钮 const createButton = screen.getByTestId('create-order-button'); fireEvent.click(createButton); // 验证订单表单模态框打开 await waitFor(() => { expect(screen.getByTestId('create-order-dialog-title')).toBeInTheDocument(); }); // 验证区域选择器组件存在 - 暂时跳过,因为OrderForm中未集成区域选择器 // expect(screen.getByTestId('area-select-mock')).toBeInTheDocument(); }); }); describe('枚举常量集成测试', () => { it('应该正确显示订单状态枚举', async () => { renderOrderManagement(); // 等待数据加载 - 验证表格中的订单状态Badge await waitFor(() => { // 使用更精确的选择器,避免与Select选项冲突 const orderRow = screen.getByTestId('order-row-1'); expect(orderRow).toBeInTheDocument(); // 验证表格中有订单状态显示 expect(screen.getByText('测试订单1')).toBeInTheDocument(); }); // 验证订单状态筛选器 const statusFilter = screen.getByTestId('filter-order-status-select'); expect(statusFilter).toBeInTheDocument(); // 点击筛选器查看选项 fireEvent.click(statusFilter); // 验证枚举选项存在 await waitFor(() => { // 使用test ID验证枚举选项 expect(screen.getByTestId('order-status-option-all')).toBeInTheDocument(); expect(screen.getByTestId('order-status-option-draft')).toBeInTheDocument(); expect(screen.getByTestId('order-status-option-confirmed')).toBeInTheDocument(); expect(screen.getByTestId('order-status-option-in-progress')).toBeInTheDocument(); expect(screen.getByTestId('order-status-option-completed')).toBeInTheDocument(); expect(screen.getByTestId('order-status-option-cancelled')).toBeInTheDocument(); }); }); it('应该正确显示工作状态枚举', async () => { renderOrderManagement(); // 等待数据加载 - 验证表格中的工作状态Badge await waitFor(() => { // 使用更精确的选择器,避免与Select选项冲突 const orderRow = screen.getByTestId('order-row-1'); expect(orderRow).toBeInTheDocument(); // 验证表格中有工作状态显示 expect(screen.getByText('测试订单1')).toBeInTheDocument(); }); // 验证工作状态筛选器 const workStatusFilter = screen.getByTestId('filter-work-status-select'); expect(workStatusFilter).toBeInTheDocument(); // 点击筛选器查看选项 fireEvent.click(workStatusFilter); // 验证枚举选项存在 await waitFor(() => { // 使用test ID验证枚举选项 expect(screen.getByTestId('work-status-option-all')).toBeInTheDocument(); expect(screen.getByTestId('work-status-option-not-working')).toBeInTheDocument(); expect(screen.getByTestId('work-status-option-pre-working')).toBeInTheDocument(); expect(screen.getByTestId('work-status-option-working')).toBeInTheDocument(); expect(screen.getByTestId('work-status-option-resigned')).toBeInTheDocument(); }); }); }); describe('人员管理测试', () => { it('应该成功打开人员选择器', async () => { renderOrderManagement(); // 等待数据加载 await waitFor(() => { expect(screen.getByTestId('order-row-1')).toBeInTheDocument(); }); // 打开订单详情弹窗 const menuTrigger = screen.getByTestId('order-menu-trigger-1'); expect(menuTrigger).toBeInTheDocument(); await userEvent.click(menuTrigger); // 点击查看详情 const viewDetailButton = screen.getByTestId('view-order-detail-button-1'); await userEvent.click(viewDetailButton); // 等待订单详情弹窗打开 await waitFor(() => { expect(screen.getByTestId('order-detail-dialog')).toBeInTheDocument(); }); // 在订单详情弹窗中点击添加人员按钮 await waitFor(() => { expect(screen.getByTestId('order-detail-card-add-persons-button')).toBeInTheDocument(); }); const addPersonsButton = screen.getByTestId('order-detail-card-add-persons-button'); await userEvent.click(addPersonsButton); // 验证残疾人选择器打开 await waitFor(() => { expect(screen.getByTestId("disabled-persons-table")).toBeInTheDocument(); }); }); it.skip('应该成功批量添加人员到已存在订单', async () => { renderOrderManagement(); // 等待数据加载 await waitFor(() => { expect(screen.getByTestId('order-row-1')).toBeInTheDocument(); }); // 打开订单详情弹窗 const menuTrigger = screen.getByTestId('order-menu-trigger-1'); expect(menuTrigger).toBeInTheDocument(); await userEvent.click(menuTrigger); // 点击查看详情 const viewDetailButton = screen.getByTestId('view-order-detail-button-1'); await userEvent.click(viewDetailButton); // 等待订单详情弹窗打开 await waitFor(() => { expect(screen.getByTestId('order-detail-dialog')).toBeInTheDocument(); }); // 在订单详情弹窗中点击添加人员按钮 await waitFor(() => { expect(screen.getByTestId('order-detail-card-add-persons-button')).toBeInTheDocument(); }); const addPersonsButton = screen.getByTestId('order-detail-card-add-persons-button'); await userEvent.click(addPersonsButton); // 验证残疾人选择器打开 await waitFor(() => { expect(screen.getByTestId("disabled-persons-table")).toBeInTheDocument(); }); // 选择人员 const selectPersonButton = screen.getByTestId('select-person-button'); await userEvent.click(selectPersonButton); // 等待残疾人选择器关闭(选择人员后会自动关闭) await waitFor(() => { expect(screen.queryByTestId('disabled-persons-table')).not.toBeInTheDocument(); }); const dialogTitle = screen.queryByTestId('batch-add-persons-dialog-title'); // 首先验证PersonSelector模态框仍然打开 await waitFor(() => { expect(screen.getByTestId('batch-add-persons-dialog-title')).toBeInTheDocument(); }); // 验证人员被添加到列表 await waitFor(() => { const personElements = screen.getAllByText('测试残疾人'); expect(personElements.length).toBeGreaterThan(0); }); // 填写人员详情 const joinDateInput = screen.getByTestId('join-date-input-1'); fireEvent.change(joinDateInput, { target: { value: '2024-01-01' } }); const salaryInput = screen.getByTestId('salary-detail-input-1'); fireEvent.change(salaryInput, { target: { value: '5000元/月' } }); const workStatusInput = screen.getByTestId('work-status-input-1'); fireEvent.change(workStatusInput, { target: { value: '在职' } }); // 提交表单 const submitButton = screen.getByRole('button', { name: /添加/ }); fireEvent.click(submitButton); // 验证API调用 await waitFor(() => { const mockOrderClient = orderClientManager.get(); // 验证批量添加人员API被调用 expect(mockOrderClient[':orderId'].persons.batch.$post).toHaveBeenCalledWith({ param: { orderId: 1 }, json: { persons: expect.arrayContaining([ expect.objectContaining({ personId: 1, joinDate: '2024-01-01', salaryDetail: '5000元/月', workStatus: 'working' }) ]) } }); }); }); }); describe('搜索和筛选测试', () => { it('应该支持按订单名称搜索', async () => { renderOrderManagement(); // 等待数据加载 await waitFor(() => { expect(screen.getByTestId('search-order-name-input')).toBeInTheDocument(); }); // 输入搜索关键词 const searchInput = screen.getByTestId('search-order-name-input'); fireEvent.change(searchInput, { target: { value: '测试订单1' } }); // 点击搜索按钮 const searchButton = screen.getByTestId('search-button'); fireEvent.click(searchButton); // 验证API调用 // 实际测试中应该验证API调用参数 }); it('应该支持按订单状态筛选', async () => { renderOrderManagement(); // 等待数据加载 await waitFor(() => { expect(screen.getByTestId('filter-order-status-select')).toBeInTheDocument(); }); // 选择订单状态 const statusFilter = screen.getByTestId('filter-order-status-select'); fireEvent.click(statusFilter); // 选择"草稿"状态 await waitFor(() => { const draftOption = screen.getByText('草稿'); fireEvent.click(draftOption); }); // 点击搜索按钮 const searchButton = screen.getByTestId('search-button'); fireEvent.click(searchButton); // 验证API调用 // 实际测试中应该验证API调用参数 }); it('应该支持按工作状态筛选', async () => { renderOrderManagement(); // 等待数据加载 await waitFor(() => { expect(screen.getByTestId('filter-work-status-select')).toBeInTheDocument(); }); // 选择工作状态 const workStatusFilter = screen.getByTestId('filter-work-status-select'); fireEvent.click(workStatusFilter); // 选择"未就业"状态 await waitFor(() => { const notWorkingOption = screen.getByText('未就业'); fireEvent.click(notWorkingOption); }); // 点击搜索按钮 const searchButton = screen.getByTestId('search-button'); fireEvent.click(searchButton); // 验证API调用 // 实际测试中应该验证API调用参数 }); it('应该支持按平台筛选', async () => { renderOrderManagement(); // 等待数据加载 await waitFor(() => { expect(screen.getByTestId('platform-search-select')).toBeInTheDocument(); }); // 平台选择器应该存在 const platformSelector = screen.getByTestId('platform-search-select'); expect(platformSelector).toBeInTheDocument(); }); it('应该支持按公司筛选', async () => { renderOrderManagement(); // 等待数据加载 await waitFor(() => { expect(screen.getByTestId('company-search-select')).toBeInTheDocument(); }); // 公司选择器应该存在 const companySelector = screen.getByTestId('company-search-select'); expect(companySelector).toBeInTheDocument(); }); it('应该支持按渠道筛选', async () => { renderOrderManagement(); // 等待数据加载 await waitFor(() => { expect(screen.getByTestId('channel-search-select')).toBeInTheDocument(); }); // 渠道选择器应该存在 const channelSelector = screen.getByTestId('channel-search-select'); expect(channelSelector).toBeInTheDocument(); }); it('应该支持按开始日期筛选', async () => { renderOrderManagement(); // 等待数据加载 await waitFor(() => { expect(screen.getByTestId('start-date-input')).toBeInTheDocument(); }); // 开始日期输入框应该存在 const startDateInput = screen.getByTestId('start-date-input'); expect(startDateInput).toBeInTheDocument(); // 设置开始日期 fireEvent.change(startDateInput, { target: { value: '2024-01-01' } }); }); it('应该支持按结束日期筛选', async () => { renderOrderManagement(); // 等待数据加载 await waitFor(() => { expect(screen.getByTestId('end-date-input')).toBeInTheDocument(); }); // 结束日期输入框应该存在 const endDateInput = screen.getByTestId('end-date-input'); expect(endDateInput).toBeInTheDocument(); // 设置结束日期 fireEvent.change(endDateInput, { target: { value: '2024-12-31' } }); }); it('应该支持重置筛选条件', async () => { renderOrderManagement(); // 等待数据加载 await waitFor(() => { expect(screen.getByTestId('reset-button')).toBeInTheDocument(); }); // 重置按钮应该存在 const resetButton = screen.getByTestId('reset-button'); expect(resetButton).toBeInTheDocument(); // 点击重置按钮 fireEvent.click(resetButton); }); }); describe('创建订单人员绑定测试', () => { it('应该成功创建订单并绑定人员', async () => { renderOrderManagement(); // 点击创建订单按钮 const createButton = screen.getByTestId('create-order-button'); await userEvent.click(createButton); // 验证订单表单模态框打开 await waitFor(() => { expect(screen.getByTestId('create-order-dialog-title')).toBeInTheDocument(); }); // 验证人员选择区域显示 // 使用更精确的选择器,避免与CardTitle中的文本冲突 await waitFor(() => { expect(screen.getByTestId('select-persons-button')).toBeInTheDocument(); }); // 验证描述文本 expect(screen.getByText('创建订单时必须至少选择一名残疾人')).toBeInTheDocument(); // 首先填写订单基本信息(在实际使用中,用户会先填写基本信息) const orderNameInput = screen.getByPlaceholderText('请输入订单名称'); fireEvent.change(orderNameInput, { target: { value: '测试订单带人员' } }); // 选择平台 - 等待平台选择器可用且启用 await waitFor(() => { const platformSelect = screen.getByTestId('platform-selector-create'); expect(platformSelect).toBeInTheDocument(); // 检查是否启用(没有disabled属性) expect(platformSelect).not.toBeDisabled(); }); // 使用共享的测试工具函数选择平台 await completeRadixSelectFlow('platform-selector-create', '1', { useFireEvent: true }); // 选择公司 - 等待启用 await waitFor(() => { const companySelect = screen.getByTestId('company-selector-create'); expect(companySelect).toBeInTheDocument(); // 检查是否启用(没有disabled属性) expect(companySelect).not.toBeDisabled(); }); // 使用共享的测试工具函数选择公司 await completeRadixSelectFlow('company-selector-create', '1', { useFireEvent: true }); // 选择渠道 - 等待启用 await waitFor(() => { const channelSelect = screen.getByTestId('channel-selector-create'); expect(channelSelect).toBeInTheDocument(); // 检查是否启用(没有disabled属性) expect(channelSelect).not.toBeDisabled(); }); // 使用共享的测试工具函数选择渠道 await completeRadixSelectFlow('channel-selector-create', '1', { useFireEvent: true }); // 现在选择残疾人 const selectPersonsButton = screen.getByTestId('select-persons-button'); fireEvent.click(selectPersonsButton); // 验证残疾人选择器打开 - 查找对话框或表格 await waitFor(() => { // 查找残疾人选择器的表格或其他元素 expect(screen.getByTestId('disabled-persons-table')).toBeInTheDocument(); }); // 选择测试人员 - 在多选模式下需要勾选复选框,然后点击确认按钮 // 首先找到复选框(在表格行的第一个单元格中) const checkbox = screen.getByRole('checkbox', { name: '选择' }); await userEvent.click(checkbox); // 然后点击确认选择按钮 const confirmButton = screen.getByTestId('confirm-batch-button'); await userEvent.click(confirmButton); // 等待残疾人选择器关闭(选择人员后会自动关闭) await waitFor(() => { expect(screen.queryByTestId('disabled-persons-table')).not.toBeInTheDocument(); }); // 验证人员被添加到列表 await waitFor(() => { // 使用getAllByText因为可能有多个元素包含相同文本 const personElements = screen.getAllByText('测试残疾人'); expect(personElements.length).toBeGreaterThan(0); const disabilityTypeElements = screen.getAllByText('肢体残疾'); expect(disabilityTypeElements.length).toBeGreaterThan(0); const levelElements = screen.getAllByText('三级'); expect(levelElements.length).toBeGreaterThan(0); }); // 注意:OrderForm中已移除"预计结束日期"和"联系人手机号"字段 // 这些字段在实际实体中不存在,已根据故事要求清理 // 填写人员详情 const salaryInput = screen.getByTestId('salary-detail-input-1'); fireEvent.change(salaryInput, { target: { value: '5000' } }); // 提交表单 const submitButton = screen.getByTestId('order-create-submit-button'); fireEvent.click(submitButton); // 验证API调用 await waitFor(() => { // 验证创建订单API被调用 const mockOrderClient = orderClientManager.get(); expect(mockOrderClient.create.$post).toHaveBeenCalledWith({ json: expect.objectContaining({ orderName: '测试订单带人员', platformId: 1, companyId: 1, channelId: 1, }) }); // 验证批量添加人员API被调用 expect(mockOrderClient[':orderId'].persons.batch.$post).toHaveBeenCalledWith({ param: { orderId: expect.any(Number) }, json: { persons: expect.arrayContaining([ expect.objectContaining({ personId: 1, salaryDetail: 5000 }) ]) } }); }); }); it('应该验证至少选择一名人员', async () => { renderOrderManagement(); // 点击创建订单按钮 const createButton = screen.getByTestId('create-order-button'); fireEvent.click(createButton); // 验证订单表单模态框打开 await waitFor(() => { expect(screen.getByTestId('create-order-dialog-title')).toBeInTheDocument(); }); // 填写订单基本信息但不选择人员 const orderNameInput = screen.getByPlaceholderText('请输入订单名称'); fireEvent.change(orderNameInput, { target: { value: '测试订单无人员' } }); // 尝试提交表单 const submitButton = screen.getByRole('button', { name: /创建/ }); fireEvent.click(submitButton); // 验证表单验证错误 await waitFor(() => { expect(screen.getByText('至少选择一名人员')).toBeInTheDocument(); }); // 验证创建订单API没有被调用 const mockOrderClient = orderClientManager.get(); expect(mockOrderClient.create.$post).not.toHaveBeenCalled(); }); }); describe('错误处理测试', () => { it('应该处理API错误', async () => { // Mock API错误 const mockOrderClient = vi.mocked(orderClientManager.get()); mockOrderClient.list.$get.mockImplementationOnce(() => Promise.resolve(createMockResponse(500, { code: 500, message: '服务器错误' })) ); renderOrderManagement(); // 验证错误处理 await waitFor(() => { expect(screen.getByText(/加载失败/)).toBeInTheDocument(); }); }); }); describe('订单详情弹窗测试', () => { let mockBatchAddPersons: any; beforeEach(() => { // 获取批量添加人员的mock函数 mockBatchAddPersons = vi.mocked(orderClientManager.get())[':orderId']?.persons?.batch?.$post; }); it('应该打开订单详情弹窗', async () => { renderOrderManagement(); // 等待订单列表加载 await waitFor(() => { expect(screen.getByTestId('order-row-1')).toBeInTheDocument(); }); // 打开操作菜单 const menuTrigger = screen.getByTestId('order-menu-trigger-1'); await userEvent.click(menuTrigger); // 点击查看详情 const viewDetailButton = screen.getByTestId('view-order-detail-button-1'); await userEvent.click(viewDetailButton); // 验证订单详情弹窗打开 await waitFor(() => { expect(screen.getByTestId('order-detail-dialog')).toBeInTheDocument(); expect(screen.getByTestId('order-detail-dialog-title')).toHaveTextContent('订单详情'); }); }); it('应该显示订单详情信息', async () => { renderOrderManagement(); // 等待订单列表加载 await waitFor(() => { expect(screen.getByTestId('order-row-1')).toBeInTheDocument(); }); // 打开操作菜单并点击查看详情 const menuTrigger = screen.getByTestId('order-menu-trigger-1'); await userEvent.click(menuTrigger); const viewDetailButton = screen.getByTestId('view-order-detail-button-1'); await userEvent.click(viewDetailButton); // 验证订单详情信息显示 await waitFor(() => { expect(screen.getByTestId('order-detail-id')).toHaveTextContent('1'); expect(screen.getByTestId('order-detail-name')).toHaveTextContent('测试订单1'); expect(screen.getByTestId('order-detail-platform')).toHaveTextContent('平台1'); expect(screen.getByTestId('order-detail-company')).toHaveTextContent('公司1'); expect(screen.getByTestId('order-detail-status')).toBeInTheDocument(); }); }); it('应该显示绑定人员列表', async () => { renderOrderManagement(); // 等待订单列表加载 await waitFor(() => { expect(screen.getByTestId('order-row-1')).toBeInTheDocument(); }); // 打开操作菜单并点击查看详情 const menuTrigger = screen.getByTestId('order-menu-trigger-1'); await userEvent.click(menuTrigger); const viewDetailButton = screen.getByTestId('view-order-detail-button-1'); await userEvent.click(viewDetailButton); // 验证人员列表显示 await waitFor(() => { // 检查是否有人员列表或"暂无绑定人员"提示 // 使用更具体的选择器,只查找订单详情弹窗内的元素 const dialog = screen.getByTestId('order-detail-dialog'); const personList = dialog.querySelector('[data-testid="order-detail-person-100"]'); const noDataMessage = dialog.querySelector('.text-center.py-8.text-muted-foreground'); expect(personList || noDataMessage).toBeInTheDocument(); }); }); it('应该支持添加人员功能', async () => { renderOrderManagement(); // 等待订单列表加载 await waitFor(() => { expect(screen.getByTestId('order-row-1')).toBeInTheDocument(); }); // 打开操作菜单并点击查看详情 const menuTrigger = screen.getByTestId('order-menu-trigger-1'); await userEvent.click(menuTrigger); const viewDetailButton = screen.getByTestId('view-order-detail-button-1'); await userEvent.click(viewDetailButton); // 点击添加人员按钮 await waitFor(() => { expect(screen.getByTestId('order-detail-card-add-persons-button')).toBeInTheDocument(); }); const addPersonsButton = screen.getByTestId('order-detail-card-add-persons-button'); await userEvent.click(addPersonsButton); // 验证残疾人选择器打开 await waitFor(() => { expect(screen.getByTestId("disabled-persons-table")).toBeInTheDocument(); }); }); it('应该支持资源上传功能', async () => { renderOrderManagement(); // 等待订单列表加载 await waitFor(() => { expect(screen.getByTestId('order-row-1')).toBeInTheDocument(); }); // 打开操作菜单并点击查看详情 const menuTrigger = screen.getByTestId('order-menu-trigger-1'); await userEvent.click(menuTrigger); const viewDetailButton = screen.getByTestId('view-order-detail-button-1'); await userEvent.click(viewDetailButton); // 点击资源上传按钮 await waitFor(() => { expect(screen.getByTestId('order-detail-bottom-add-asset-button')).toBeInTheDocument(); }); const addAssetButton = screen.getByTestId('order-detail-bottom-add-asset-button'); await userEvent.click(addAssetButton); // 验证资产关联模态框打开 await waitFor(() => { expect(screen.getByTestId('order-asset-modal-title')).toBeInTheDocument(); }); }); it('应该根据订单状态显示激活/关闭按钮', async () => { renderOrderManagement(); // 等待订单列表加载 await waitFor(() => { expect(screen.getByTestId('order-row-1')).toBeInTheDocument(); }); // 打开操作菜单并点击查看详情 const menuTrigger = screen.getByTestId('order-menu-trigger-1'); await userEvent.click(menuTrigger); const viewDetailButton = screen.getByTestId('view-order-detail-button-1'); await userEvent.click(viewDetailButton); // 根据订单状态验证按钮显示 await waitFor(() => { // 订单1的状态是DRAFT,应该显示激活按钮 const activateButton = screen.queryByTestId('order-detail-activate-button'); const closeButton = screen.queryByTestId('order-detail-close-order-button'); // 根据mock数据,订单1的状态是DRAFT expect(activateButton).toBeInTheDocument(); expect(closeButton).not.toBeInTheDocument(); }); }); it('应该关闭订单详情弹窗', async () => { renderOrderManagement(); // 等待订单列表加载 await waitFor(() => { expect(screen.getByTestId('order-row-1')).toBeInTheDocument(); }); // 打开操作菜单并点击查看详情 const menuTrigger = screen.getByTestId('order-menu-trigger-1'); await userEvent.click(menuTrigger); const viewDetailButton = screen.getByTestId('view-order-detail-button-1'); await userEvent.click(viewDetailButton); // 验证弹窗打开 await waitFor(() => { expect(screen.getByTestId('order-detail-dialog')).toBeInTheDocument(); }); // 点击关闭按钮 const closeButton = screen.getByTestId('order-detail-close-button'); await userEvent.click(closeButton); // 验证弹窗关闭 await waitFor(() => { expect(screen.queryByTestId('order-detail-dialog')).not.toBeInTheDocument(); }); }); it.skip('应该将选择的人员添加到待添加列表而不是立即调用API', async () => { renderOrderManagement(); // 等待订单列表加载 await waitFor(() => { expect(screen.getByTestId('order-row-1')).toBeInTheDocument(); }); // 打开操作菜单并点击查看详情 const menuTrigger = screen.getByTestId('order-menu-trigger-1'); await userEvent.click(menuTrigger); const viewDetailButton = screen.getByTestId('view-order-detail-button-1'); await userEvent.click(viewDetailButton); // 点击添加人员按钮 await waitFor(() => { expect(screen.getByTestId('order-detail-card-add-persons-button')).toBeInTheDocument(); }); const addPersonsButton = screen.getByTestId('order-detail-card-add-persons-button'); await userEvent.click(addPersonsButton); // 验证残疾人选择器打开 await waitFor(() => { expect(screen.getByTestId("disabled-persons-table")).toBeInTheDocument(); }); // 选择人员 const selectPersonButton = screen.getByTestId('select-person-button'); await userEvent.click(selectPersonButton); // 等待残疾人选择器自动关闭(选择人员后自动关闭) await waitFor(() => { expect(screen.queryByTestId('disabled-person-selector-real')).not.toBeInTheDocument(); }); // 等待handlePersonSelect完成 await waitFor(() => { // 检查toast是否显示 screen.queryByText(/已添加.*名人员到待添加列表/); }, { timeout: 3000 }); // 验证待添加人员列表显示 await waitFor(() => { expect(screen.getByTestId('pending-persons-card')).toBeInTheDocument(); expect(screen.getByTestId('pending-person-1')).toBeInTheDocument(); }, { timeout: 5000 }); // 验证确认添加按钮显示正确数量 const confirmButton = screen.getByTestId('confirm-add-persons-button'); expect(confirmButton).toHaveTextContent('确认添加 (1)'); // 验证没有立即调用批量添加API expect(mockBatchAddPersons).not.toHaveBeenCalled(); }); it.skip('应该支持编辑待添加人员的薪资', async () => { renderOrderManagement(); // 等待订单列表加载 await waitFor(() => { expect(screen.getByTestId('order-row-1')).toBeInTheDocument(); }); // 打开操作菜单并点击查看详情 const menuTrigger = screen.getByTestId('order-menu-trigger-1'); await userEvent.click(menuTrigger); const viewDetailButton = screen.getByTestId('view-order-detail-button-1'); await userEvent.click(viewDetailButton); // 点击添加人员按钮并选择人员 const addPersonsButton = screen.getByTestId('order-detail-card-add-persons-button'); await userEvent.click(addPersonsButton); await waitFor(() => { expect(screen.getByTestId("disabled-persons-table")).toBeInTheDocument(); }); const selectPersonButton = screen.getByTestId('select-person-button'); await userEvent.click(selectPersonButton); // 关闭残疾人选择器 const closeSelectorButton = screen.getByTestId('close-selector-button'); await userEvent.click(closeSelectorButton); // 等待待添加人员列表显示 await waitFor(() => { expect(screen.getByTestId('pending-persons-card')).toBeInTheDocument(); }); // 编辑薪资 const salaryInput = screen.getByTestId('pending-person-salary-input-1'); await userEvent.clear(salaryInput); await userEvent.type(salaryInput, '8000'); // 验证薪资已更新 expect(salaryInput).toHaveValue(8000); }); it.skip('应该支持从待添加列表中移除人员', async () => { renderOrderManagement(); // 等待订单列表加载 await waitFor(() => { expect(screen.getByTestId('order-row-1')).toBeInTheDocument(); }); // 打开操作菜单并点击查看详情 const menuTrigger = screen.getByTestId('order-menu-trigger-1'); await userEvent.click(menuTrigger); const viewDetailButton = screen.getByTestId('view-order-detail-button-1'); await userEvent.click(viewDetailButton); // 点击添加人员按钮并选择人员 const addPersonsButton = screen.getByTestId('order-detail-card-add-persons-button'); await userEvent.click(addPersonsButton); await waitFor(() => { expect(screen.getByTestId("disabled-persons-table")).toBeInTheDocument(); }); const selectPersonButton = screen.getByTestId('select-person-button'); await userEvent.click(selectPersonButton); // 关闭残疾人选择器 const closeSelectorButton = screen.getByTestId('close-selector-button'); await userEvent.click(closeSelectorButton); // 等待待添加人员列表显示 await waitFor(() => { expect(screen.getByTestId('pending-persons-card')).toBeInTheDocument(); }); // 移除人员 const removeButton = screen.getByTestId('remove-pending-person-button-1'); await userEvent.click(removeButton); // 验证人员已从列表中移除 await waitFor(() => { expect(screen.queryByTestId('pending-person-1')).not.toBeInTheDocument(); }); }); it.skip('应该点击确认添加按钮后调用批量添加API', async () => { renderOrderManagement(); // 等待订单列表加载 await waitFor(() => { expect(screen.getByTestId('order-row-1')).toBeInTheDocument(); }); // 打开操作菜单并点击查看详情 const menuTrigger = screen.getByTestId('order-menu-trigger-1'); await userEvent.click(menuTrigger); const viewDetailButton = screen.getByTestId('view-order-detail-button-1'); await userEvent.click(viewDetailButton); // 点击添加人员按钮并选择人员 const addPersonsButton = screen.getByTestId('order-detail-card-add-persons-button'); await userEvent.click(addPersonsButton); await waitFor(() => { expect(screen.getByTestId("disabled-persons-table")).toBeInTheDocument(); }); const selectPersonButton = screen.getByTestId('select-person-button'); await userEvent.click(selectPersonButton); // 关闭残疾人选择器 const closeSelectorButton = screen.getByTestId('close-selector-button'); await userEvent.click(closeSelectorButton); // 等待待添加人员列表显示 await waitFor(() => { expect(screen.getByTestId('pending-persons-card')).toBeInTheDocument(); }); // 点击确认添加按钮 const confirmButton = screen.getByTestId('confirm-add-persons-button'); await userEvent.click(confirmButton); // 验证批量添加API被调用 await waitFor(() => { expect(mockBatchAddPersons).toHaveBeenCalledTimes(1); }); // 验证API调用参数正确 expect(mockBatchAddPersons).toHaveBeenCalledWith( expect.objectContaining({ param: { orderId: 1 }, json: expect.objectContaining({ persons: expect.arrayContaining([ expect.objectContaining({ personId: 1, salaryDetail: expect.any(Number), joinDate: expect.stringMatching(/^\d{4}-\d{2}-\d{2}$/), // YYYY-MM-DD格式 workStatus: WorkStatus.NOT_WORKING }) ]) }) }) ); }); it.skip('应该避免重复添加已在订单中或已在待添加列表中的人员', async () => { renderOrderManagement(); // 等待订单列表加载 await waitFor(() => { expect(screen.getByTestId('order-row-1')).toBeInTheDocument(); }); // 打开操作菜单并点击查看详情 const menuTrigger = screen.getByTestId('order-menu-trigger-1'); await userEvent.click(menuTrigger); const viewDetailButton = screen.getByTestId('view-order-detail-button-1'); await userEvent.click(viewDetailButton); // 等待订单详情弹窗打开 await waitFor(() => { expect(screen.getByTestId('order-detail-dialog')).toBeInTheDocument(); }); // 点击添加人员按钮 const addPersonsButton = screen.getByTestId('order-detail-card-add-persons-button'); await userEvent.click(addPersonsButton); await waitFor(() => { expect(screen.getByTestId("disabled-persons-table")).toBeInTheDocument(); }); // 第一次选择人员 const selectPersonButton = screen.getByTestId('select-person-button'); await userEvent.click(selectPersonButton); // 关闭残疾人选择器 const closeSelectorButton = screen.getByTestId('close-selector-button'); await userEvent.click(closeSelectorButton); // 等待待添加人员列表显示 await waitFor(() => { expect(screen.getByTestId('pending-persons-card')).toBeInTheDocument(); }); // 再次打开选择器并选择相同人员 await userEvent.click(addPersonsButton); await waitFor(() => { expect(screen.getByTestId("disabled-persons-table")).toBeInTheDocument(); }); await userEvent.click(selectPersonButton); // 验证待添加人员列表仍然只有1人(没有重复添加) await waitFor(() => { const pendingPersonRows = screen.getAllByTestId(/^pending-person-/); expect(pendingPersonRows).toHaveLength(1); }); }); }); });