import React from 'react'; import { describe, it, expect, vi, beforeEach } from 'vitest'; import { render, screen, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { TestWrapper } from '../../__test_utils__/test-render'; import { TestRouter } from '../../__test_utils__/test-router'; import { TestQueryProvider } from '../../__test_utils__/test-query'; // 模拟的表单组件 function LoginForm({ onSubmit }: { onSubmit: (data: any) => Promise }) { const [email, setEmail] = React.useState(''); const [password, setPassword] = React.useState(''); const [isSubmitting, setIsSubmitting] = React.useState(false); const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); setIsSubmitting(true); try { await onSubmit({ email, password }); } catch (error) { console.error('Login failed:', error); } finally { setIsSubmitting(false); } }; return (
setEmail(e.target.value)} required data-testid="email-input" />
setPassword(e.target.value)} required data-testid="password-input" />
); } // 模拟的登录页面组件 function LoginPage() { const loginMutation = { mutateAsync: vi.fn().mockResolvedValue({ success: true }), isLoading: false, }; const handleLogin = async (credentials: any) => { return loginMutation.mutateAsync(credentials); }; return (

Login

); } describe('Form Component Integration Tests', () => { let user: ReturnType; let loginMock: any; beforeEach(() => { user = userEvent.setup(); loginMock = vi.fn().mockResolvedValue({ success: true }); }); it('应该渲染表单并包含所有必要的字段', () => { render( ); expect(screen.getByTestId('login-form')).toBeInTheDocument(); expect(screen.getByTestId('email-input')).toBeInTheDocument(); expect(screen.getByTestId('password-input')).toBeInTheDocument(); expect(screen.getByTestId('submit-button')).toBeInTheDocument(); }); it('应该允许用户输入邮箱和密码', async () => { render( ); const emailInput = screen.getByTestId('email-input'); const passwordInput = screen.getByTestId('password-input'); await user.type(emailInput, 'test@example.com'); await user.type(passwordInput, 'password123'); expect(emailInput).toHaveValue('test@example.com'); expect(passwordInput).toHaveValue('password123'); }); it('应该在表单提交时调用onSubmit回调', async () => { render( ); await user.type(screen.getByTestId('email-input'), 'test@example.com'); await user.type(screen.getByTestId('password-input'), 'password123'); await user.click(screen.getByTestId('submit-button')); await waitFor(() => { expect(loginMock).toHaveBeenCalledWith({ email: 'test@example.com', password: 'password123' }); }); }); it('应该在提交时显示加载状态', async () => { const slowLoginMock = vi.fn().mockImplementation( () => new Promise(resolve => setTimeout(() => resolve({ success: true }), 100)) ); render( ); await user.type(screen.getByTestId('email-input'), 'test@example.com'); await user.type(screen.getByTestId('password-input'), 'password123'); await user.click(screen.getByTestId('submit-button')); expect(screen.getByTestId('submit-button')).toBeDisabled(); expect(screen.getByTestId('submit-button')).toHaveTextContent('Logging in...'); await waitFor(() => { expect(screen.getByTestId('submit-button')).not.toBeDisabled(); }); }); it('应该与React Router集成', () => { render( ); expect(screen.getByRole('heading', { name: 'Login' })).toBeInTheDocument(); expect(screen.getByTestId('login-form')).toBeInTheDocument(); }); it('应该处理表单验证错误', async () => { const errorMock = vi.fn().mockRejectedValue(new Error('Invalid credentials')); render( ); // 不填写必填字段直接提交 await user.click(screen.getByTestId('submit-button')); // 检查表单仍然可见(没有因为错误而崩溃) expect(screen.getByTestId('login-form')).toBeInTheDocument(); }); it('应该支持键盘导航和辅助功能', async () => { render( ); const emailInput = screen.getByTestId('email-input'); const passwordInput = screen.getByTestId('password-input'); const submitButton = screen.getByTestId('submit-button'); // Tab 导航 await user.tab(); expect(emailInput).toHaveFocus(); await user.tab(); expect(passwordInput).toHaveFocus(); await user.tab(); expect(submitButton).toHaveFocus(); // Enter 提交 await user.type(emailInput, 'test@example.com'); await user.type(passwordInput, 'password123'); await user.keyboard('{Enter}'); await waitFor(() => { expect(loginMock).toHaveBeenCalled(); }); }); });