|
@@ -0,0 +1,141 @@
|
|
|
|
|
+import React from 'react';
|
|
|
|
|
+import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
|
|
|
+import { screen, fireEvent, waitFor } from '@testing-library/react';
|
|
|
|
|
+import { LoginPage } from '../../src/components/LoginPage';
|
|
|
|
|
+import { AuthProvider } from '../../src/hooks/AuthProvider';
|
|
|
|
|
+import { renderWithProviders } from '../test-utils';
|
|
|
|
|
+
|
|
|
|
|
+// Mock react-router
|
|
|
|
|
+vi.mock('react-router', () => ({
|
|
|
|
|
+ useNavigate: () => vi.fn(),
|
|
|
|
|
+}));
|
|
|
|
|
+
|
|
|
|
|
+// Mock sonner
|
|
|
|
|
+vi.mock('sonner', () => ({
|
|
|
|
|
+ toast: {
|
|
|
|
|
+ success: vi.fn(),
|
|
|
|
|
+ error: vi.fn(),
|
|
|
|
|
+ },
|
|
|
|
|
+}));
|
|
|
|
|
+
|
|
|
|
|
+// Mock shared UI components - 使用data-testid策略
|
|
|
|
|
+vi.mock('@d8d/shared-ui-components', () => ({
|
|
|
|
|
+ Button: ({ children, ...props }: any) => {
|
|
|
|
|
+ const { render, handleSubmit, setValue, getValues, resetField, clearErrors, setError, setFocus, getFieldState, formState, subscribe, trigger, register, watch, reset, unregister, ...safeProps } = props;
|
|
|
|
|
+ return React.createElement('button', { ...safeProps, 'data-testid': 'button' }, children);
|
|
|
|
|
+ },
|
|
|
|
|
+ Card: ({ children, ...props }: any) => {
|
|
|
|
|
+ const { render, handleSubmit, setValue, getValues, resetField, clearErrors, setError, setFocus, getFieldState, formState, subscribe, trigger, register, watch, reset, unregister, ...safeProps } = props;
|
|
|
|
|
+ return React.createElement('div', { ...safeProps, 'data-testid': 'card' }, children);
|
|
|
|
|
+ },
|
|
|
|
|
+ CardContent: ({ children, ...props }: any) => {
|
|
|
|
|
+ const { render, handleSubmit, setValue, getValues, resetField, clearErrors, setError, setFocus, getFieldState, formState, subscribe, trigger, register, watch, reset, unregister, ...safeProps } = props;
|
|
|
|
|
+ return React.createElement('div', { ...safeProps, 'data-testid': 'card-content' }, children);
|
|
|
|
|
+ },
|
|
|
|
|
+ CardDescription: ({ children, ...props }: any) => {
|
|
|
|
|
+ const { render, handleSubmit, setValue, getValues, resetField, clearErrors, setError, setFocus, getFieldState, formState, subscribe, trigger, register, watch, reset, unregister, ...safeProps } = props;
|
|
|
|
|
+ return React.createElement('div', { ...safeProps, 'data-testid': 'card-description' }, children);
|
|
|
|
|
+ },
|
|
|
|
|
+ CardFooter: ({ children, ...props }: any) => {
|
|
|
|
|
+ const { render, handleSubmit, setValue, getValues, resetField, clearErrors, setError, setFocus, getFieldState, formState, subscribe, trigger, register, watch, reset, unregister, ...safeProps } = props;
|
|
|
|
|
+ return React.createElement('div', { ...safeProps, 'data-testid': 'card-footer' }, children);
|
|
|
|
|
+ },
|
|
|
|
|
+ CardHeader: ({ children, ...props }: any) => {
|
|
|
|
|
+ const { render, handleSubmit, setValue, getValues, resetField, clearErrors, setError, setFocus, getFieldState, formState, subscribe, trigger, register, watch, reset, unregister, ...safeProps } = props;
|
|
|
|
|
+ return React.createElement('div', { ...safeProps, 'data-testid': 'card-header' }, children);
|
|
|
|
|
+ },
|
|
|
|
|
+ CardTitle: ({ children, ...props }: any) => {
|
|
|
|
|
+ const { render, handleSubmit, setValue, getValues, resetField, clearErrors, setError, setFocus, getFieldState, formState, subscribe, trigger, register, watch, reset, unregister, ...safeProps } = props;
|
|
|
|
|
+ return React.createElement('div', { ...safeProps, 'data-testid': 'card-title' }, children);
|
|
|
|
|
+ },
|
|
|
|
|
+ Form: ({ children, ...props }: any) => {
|
|
|
|
|
+ const { render, handleSubmit, setValue, getValues, resetField, clearErrors, setError, setFocus, getFieldState, formState, subscribe, trigger, register, watch, reset, unregister, ...safeProps } = props;
|
|
|
|
|
+ return React.createElement('div', { ...safeProps, 'data-testid': 'form' }, children);
|
|
|
|
|
+ },
|
|
|
|
|
+ FormControl: ({ children, ...props }: any) => {
|
|
|
|
|
+ const { render, handleSubmit, setValue, getValues, resetField, clearErrors, setError, setFocus, getFieldState, formState, subscribe, trigger, register, watch, reset, unregister, ...safeProps } = props;
|
|
|
|
|
+ return React.createElement('div', { ...safeProps, 'data-testid': 'form-control' }, children);
|
|
|
|
|
+ },
|
|
|
|
|
+ FormField: ({ children, ...props }: any) => {
|
|
|
|
|
+ const { render, handleSubmit, setValue, getValues, resetField, clearErrors, setError, setFocus, getFieldState, formState, subscribe, trigger, register, watch, reset, unregister, ...safeProps } = props;
|
|
|
|
|
+ // FormField有一个render函数,需要处理
|
|
|
|
|
+ if (props.render) {
|
|
|
|
|
+ return props.render({ field: {} });
|
|
|
|
|
+ }
|
|
|
|
|
+ return React.createElement('div', { ...safeProps, 'data-testid': 'form-field', name: props.name }, children);
|
|
|
|
|
+ },
|
|
|
|
|
+ FormItem: ({ children, ...props }: any) => {
|
|
|
|
|
+ const { render, handleSubmit, setValue, getValues, resetField, clearErrors, setError, setFocus, getFieldState, formState, subscribe, trigger, register, watch, reset, unregister, ...safeProps } = props;
|
|
|
|
|
+ return React.createElement('div', { ...safeProps, 'data-testid': 'form-item' }, children);
|
|
|
|
|
+ },
|
|
|
|
|
+ FormLabel: ({ children, ...props }: any) => {
|
|
|
|
|
+ const { render, handleSubmit, setValue, getValues, resetField, clearErrors, setError, setFocus, getFieldState, formState, subscribe, trigger, register, watch, reset, unregister, ...safeProps } = props;
|
|
|
|
|
+ return React.createElement('label', { ...safeProps, 'data-testid': 'form-label' }, children);
|
|
|
|
|
+ },
|
|
|
|
|
+ FormMessage: ({ children, ...props }: any) => {
|
|
|
|
|
+ const { render, handleSubmit, setValue, getValues, resetField, clearErrors, setError, setFocus, getFieldState, formState, subscribe, trigger, register, watch, reset, unregister, ...safeProps } = props;
|
|
|
|
|
+ return React.createElement('div', { ...safeProps, 'data-testid': 'form-message' }, children);
|
|
|
|
|
+ },
|
|
|
|
|
+ Input: ({ ...props }: any) => {
|
|
|
|
|
+ const { render, handleSubmit, setValue, getValues, resetField, clearErrors, setError, setFocus, getFieldState, formState, subscribe, trigger, register, watch, reset, unregister, ...safeProps } = props;
|
|
|
|
|
+ return React.createElement('input', { ...safeProps, 'data-testid': 'input' });
|
|
|
|
|
+ },
|
|
|
|
|
+ Building: ({ ...props }: any) => {
|
|
|
|
|
+ return React.createElement('div', { 'data-testid': 'building-icon' });
|
|
|
|
|
+ },
|
|
|
|
|
+}));
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+describe('LoginPage', () => {
|
|
|
|
|
+ beforeEach(() => {
|
|
|
|
|
+ vi.clearAllMocks();
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ const renderWithAuthProvider = (component: React.ReactElement) => {
|
|
|
|
|
+ return renderWithProviders(
|
|
|
|
|
+ <AuthProvider>
|
|
|
|
|
+ {component}
|
|
|
|
|
+ </AuthProvider>
|
|
|
|
|
+ );
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ it('应该渲染登录页面', () => {
|
|
|
|
|
+ renderWithAuthProvider(<LoginPage />);
|
|
|
|
|
+
|
|
|
|
|
+ // 验证页面基本结构
|
|
|
|
|
+ expect(screen.getByTestId('card')).toBeInTheDocument();
|
|
|
|
|
+ expect(screen.getByTestId('form')).toBeInTheDocument();
|
|
|
|
|
+ expect(screen.getByTestId('button')).toBeInTheDocument();
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ it('应该显示用户名和密码输入框', () => {
|
|
|
|
|
+ renderWithAuthProvider(<LoginPage />);
|
|
|
|
|
+
|
|
|
|
|
+ // 验证输入框存在
|
|
|
|
|
+ const inputs = screen.getAllByTestId('input');
|
|
|
|
|
+ expect(inputs.length).toBeGreaterThan(0);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ it('应该显示登录按钮', () => {
|
|
|
|
|
+ renderWithAuthProvider(<LoginPage />);
|
|
|
|
|
+
|
|
|
|
|
+ // 验证按钮存在
|
|
|
|
|
+ const buttons = screen.getAllByTestId('button');
|
|
|
|
|
+ expect(buttons.length).toBeGreaterThan(0);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ it('应该显示租户ID输入框', () => {
|
|
|
|
|
+ renderWithAuthProvider(<LoginPage />);
|
|
|
|
|
+
|
|
|
|
|
+ // 验证租户ID输入框存在
|
|
|
|
|
+ const inputs = screen.getAllByTestId('input');
|
|
|
|
|
+ expect(inputs.length).toBeGreaterThanOrEqual(3); // 用户名、密码、租户ID
|
|
|
|
|
+
|
|
|
|
|
+ // 验证租户ID标签存在
|
|
|
|
|
+ const formLabels = screen.getAllByTestId('form-label');
|
|
|
|
|
+ const hasTenantLabel = formLabels.some(label =>
|
|
|
|
|
+ label.textContent?.includes('租户ID')
|
|
|
|
|
+ );
|
|
|
|
|
+ expect(hasTenantLabel).toBe(true);
|
|
|
|
|
+ });
|
|
|
|
|
+});
|