import { describe, it, expect, vi, beforeEach } from 'vitest'; import { render, screen, fireEvent, waitFor, act } from '@testing-library/react'; import { useForm, FormProvider } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; import { z } from 'zod'; import { AreaSelectForm } from '../../src/components/AreaSelectForm'; import { Button } from '@d8d/shared-ui-components/components/ui/button'; import { Form } from '@d8d/shared-ui-components/components/ui/form'; // 测试用的schema const TestSchema = z.object({ province: z.string().min(1, '省份不能为空'), city: z.string().min(1, '城市不能为空'), district: z.string().optional(), }); type TestFormData = z.infer; // Mock AreaSelect 组件 vi.mock('../../src/components/AreaSelect', () => ({ AreaSelect: vi.fn(({ value, onChange, disabled, required }) => { return (
); }), })); // 测试组件 const TestForm = () => { const form = useForm({ resolver: zodResolver(TestSchema), defaultValues: { province: '', city: '', district: '', }, mode: 'onSubmit', // 使用onSubmit模式,这是默认值 }); const onSubmit = vi.fn(); return (
provinceName="province" cityName="city" districtName="district" label="地区选择" required={true} control={form.control} />
); }; describe('AreaSelectForm 集成测试', () => { beforeEach(() => { vi.clearAllMocks(); }); it('应该正确渲染AreaSelectForm组件', () => { render(); expect(screen.getByText('地区选择')).toBeInTheDocument(); // 检查是否包含必填标记(星号) const label = screen.getByText('地区选择'); expect(label.parentElement).toContainHTML('*'); expect(screen.getByTestId('area-select')).toBeInTheDocument(); }); it('应该显示省份和城市的验证错误当表单提交时', async () => { let formRef: any; const TestFormWithRef = () => { const form = useForm({ resolver: zodResolver(TestSchema), defaultValues: { province: '', city: '', district: '', }, mode: 'onSubmit', }); formRef = form; const onSubmit = vi.fn(); return (
provinceName="province" cityName="city" districtName="district" label="地区选择" required={true} control={form.control} />
); }; render(); // 初始状态不应该有验证错误 expect(screen.queryByText('省份不能为空')).not.toBeInTheDocument(); expect(screen.queryByText('城市不能为空')).not.toBeInTheDocument(); // 提交表单(不选择任何省份和城市) const submitButton = screen.getByTestId('submit-button'); await act(async () => { fireEvent.click(submitButton); }); // 等待一下,让验证完成 await new Promise(resolve => setTimeout(resolve, 100)); // 等待验证错误显示 await waitFor(() => { expect(screen.getByText('省份不能为空')).toBeInTheDocument(); expect(screen.getByText('城市不能为空')).toBeInTheDocument(); }, { timeout: 3000 }); }); it('应该正确更新表单字段值当选择省份和城市时', async () => { render(); // 选择省份 const provinceSelect = screen.getByTestId('province-select'); fireEvent.change(provinceSelect, { target: { value: '1' } }); // 选择城市 const citySelect = screen.getByTestId('city-select'); fireEvent.change(citySelect, { target: { value: '3' } }); // 提交表单 const submitButton = screen.getByTestId('submit-button'); fireEvent.click(submitButton); // 不应该有验证错误 await waitFor(() => { expect(screen.queryByText('省份不能为空')).not.toBeInTheDocument(); expect(screen.queryByText('城市不能为空')).not.toBeInTheDocument(); }); }); it('应该显示验证错误当只选择省份不选择城市时', async () => { render(); // 只选择省份 const provinceSelect = screen.getByTestId('province-select'); fireEvent.change(provinceSelect, { target: { value: '1' } }); // 提交表单 const submitButton = screen.getByTestId('submit-button'); fireEvent.click(submitButton); // 应该只有城市验证错误 await waitFor(() => { expect(screen.queryByText('省份不能为空')).not.toBeInTheDocument(); expect(screen.getByText('城市不能为空')).toBeInTheDocument(); }); }); it('应该显示验证错误当只选择城市不选择省份时', async () => { render(); // 只选择城市 const citySelect = screen.getByTestId('city-select'); fireEvent.change(citySelect, { target: { value: '3' } }); // 提交表单 const submitButton = screen.getByTestId('submit-button'); fireEvent.click(submitButton); // 应该只有省份验证错误 await waitFor(() => { expect(screen.getByText('省份不能为空')).toBeInTheDocument(); expect(screen.queryByText('城市不能为空')).not.toBeInTheDocument(); }); }); it('应该正确处理区县字段(可选)', async () => { render(); // 选择省份和城市 const provinceSelect = screen.getByTestId('province-select'); const citySelect = screen.getByTestId('city-select'); fireEvent.change(provinceSelect, { target: { value: '1' } }); fireEvent.change(citySelect, { target: { value: '3' } }); // 选择区县(可选) const districtSelect = screen.getByTestId('district-select'); fireEvent.change(districtSelect, { target: { value: '5' } }); // 提交表单 const submitButton = screen.getByTestId('submit-button'); fireEvent.click(submitButton); // 不应该有验证错误 await waitFor(() => { expect(screen.queryByText('省份不能为空')).not.toBeInTheDocument(); expect(screen.queryByText('城市不能为空')).not.toBeInTheDocument(); }); }); it('应该支持禁用状态', () => { const DisabledTestForm = () => { const form = useForm({ resolver: zodResolver(TestSchema), defaultValues: { province: '', city: '', district: '', }, }); return (
provinceName="province" cityName="city" districtName="district" label="地区选择" required={true} disabled={true} control={form.control} />
); }; render(); const provinceSelect = screen.getByTestId('province-select'); const citySelect = screen.getByTestId('city-select'); const districtSelect = screen.getByTestId('district-select'); expect(provinceSelect).toBeDisabled(); expect(citySelect).toBeDisabled(); expect(districtSelect).toBeDisabled(); }); });