import React from 'react'; import { render, screen, fireEvent, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { vi } from 'vitest'; import AttendanceModal from '../../src/components/AttendanceModal'; // Mock xlsx vi.mock('xlsx', () => ({ __esModule: true, default: { utils: { book_new: vi.fn(() => ({})), aoa_to_sheet: vi.fn(() => ({})), book_append_sheet: vi.fn(), }, writeFile: vi.fn(), }, utils: { book_new: vi.fn(() => ({})), aoa_to_sheet: vi.fn(() => ({})), book_append_sheet: vi.fn(), }, writeFile: vi.fn(), })); // Mock sonner toast vi.mock('sonner', () => ({ toast: { success: vi.fn(), error: vi.fn(), warning: vi.fn(), }, })); describe('AttendanceModal', () => { const mockOrderPersons = [ { personId: 1, personName: '张三', disabilityId: 'D001', disabilityType: '肢体残疾', }, { personId: 2, personName: '李四', disabilityId: 'D002', disabilityType: '视力残疾', }, ]; const defaultProps = { open: true, onOpenChange: vi.fn(), orderId: 123, orderName: '测试订单', orderPersons: mockOrderPersons, }; beforeEach(() => { vi.clearAllMocks(); }); it('应该正确渲染AttendanceModal组件', () => { render(); expect(screen.getByTestId('attendance-modal')).toBeInTheDocument(); expect(screen.getByTestId('attendance-modal-title')).toHaveTextContent('出勤表导出'); expect(screen.getByText(/为订单"测试订单"生成月度出勤Excel表/)).toBeInTheDocument(); expect(screen.getByTestId('attendance-month-select')).toBeInTheDocument(); expect(screen.getByTestId('attendance-days-select')).toBeInTheDocument(); expect(screen.getByTestId('attendance-generate-button')).toBeInTheDocument(); expect(screen.getByTestId('attendance-cancel-button')).toBeInTheDocument(); }); it('应该显示订单信息', () => { render(); expect(screen.getByText('订单名称:')).toBeInTheDocument(); expect(screen.getByText('测试订单')).toBeInTheDocument(); expect(screen.getByText('订单ID:')).toBeInTheDocument(); expect(screen.getByText('123')).toBeInTheDocument(); expect(screen.getByText('人员数量:')).toBeInTheDocument(); expect(screen.getByText('2人')).toBeInTheDocument(); }); it('应该显示月份选择器', () => { render(); const monthSelect = screen.getByTestId('attendance-month-select'); expect(monthSelect).toBeInTheDocument(); expect(screen.getByText('选择月份')).toBeInTheDocument(); }); it('应该显示出勤天数选择器', () => { render(); const daysSelect = screen.getByTestId('attendance-days-select'); expect(daysSelect).toBeInTheDocument(); expect(screen.getByText('出勤天数')).toBeInTheDocument(); }); it('应该显示出勤表预览信息', () => { render(); expect(screen.getByText('表格结构:')).toBeInTheDocument(); expect(screen.getByText(/列: 姓名、残疾证号、残疾类型、1-20日、出勤天数、缺勤天数、备注/)).toBeInTheDocument(); expect(screen.getByText(/行: 2名人员/)).toBeInTheDocument(); expect(screen.getByText(/出勤标记: √ \(出勤\), 空白 \(缺勤\)/)).toBeInTheDocument(); expect(screen.getByText(/文件格式: Excel \(\.xlsx\)/)).toBeInTheDocument(); }); it('应该在没有人员时禁用生成按钮', () => { const propsWithoutPersons = { ...defaultProps, orderPersons: [], }; render(); const generateButton = screen.getByTestId('attendance-generate-button'); expect(generateButton).toBeDisabled(); }); it('应该在有人员时启用生成按钮', () => { render(); const generateButton = screen.getByTestId('attendance-generate-button'); expect(generateButton).toBeEnabled(); }); it('应该点击取消按钮关闭模态框', async () => { const user = userEvent.setup(); const onOpenChange = vi.fn(); render(); const cancelButton = screen.getByTestId('attendance-cancel-button'); await user.click(cancelButton); expect(onOpenChange).toHaveBeenCalledWith(false); }); it('应该在没有人员时显示警告并阻止生成', async () => { const user = userEvent.setup(); const propsWithoutPersons = { ...defaultProps, orderPersons: [], }; const { toast } = await import('sonner'); render(); const form = screen.getByRole('form'); fireEvent.submit(form); await waitFor(() => { expect(toast.warning).toHaveBeenCalledWith('订单中没有人员,无法生成出勤表'); }); }); it('应该显示生成按钮', () => { render(); const generateButton = screen.getByTestId('attendance-generate-button'); expect(generateButton).toBeInTheDocument(); expect(generateButton).toHaveTextContent('生成出勤表'); }); it('应该显示取消按钮', () => { render(); const cancelButton = screen.getByTestId('attendance-cancel-button'); expect(cancelButton).toBeInTheDocument(); expect(cancelButton).toHaveTextContent('取消'); }); });