添加测试配置及登陆部分的测试
Change-Id: I6fa1fe23ad8773548927fdc921dceab841f2368a
diff --git a/test/login.test.tsx b/test/login.test.tsx
new file mode 100644
index 0000000..936d9fb
--- /dev/null
+++ b/test/login.test.tsx
@@ -0,0 +1,92 @@
+import React from 'react';
+import { render, screen, fireEvent, waitFor } from '@testing-library/react';
+import '@testing-library/jest-dom';
+import Login from '../src/views/login/login';
+import { useApi } from '@/hooks/request';
+import { useAppDispatch } from '@/hooks/store';
+import { useNavigate } from 'react-router';
+import { useSelector } from 'react-redux';
+
+
+jest.mock('@/hooks/request', () => ({
+ useApi: jest.fn(),
+}));
+// 模拟所有外部依赖
+jest.mock('@/hooks/store', () => ({
+ useAppDispatch: jest.fn(),
+}));
+
+jest.mock('react-router', () => ({
+ useNavigate: jest.fn(),
+}));
+
+jest.mock('react-redux', () => ({
+ useSelector: jest.fn(),
+}));
+
+// 类型安全:明确模拟函数的返回类型
+const mockUseApi = useApi as jest.MockedFunction<typeof useApi>;
+const mockUseAppDispatch = useAppDispatch as jest.MockedFunction<typeof useAppDispatch>;
+const mockUseNavigate = useNavigate as jest.MockedFunction<typeof useNavigate>;
+const mockUseSelector = useSelector as jest.MockedFunction<typeof useSelector>;
+
+describe('Login Component', () => {
+ const mockDispatch = jest.fn();
+ const mockNavigate = jest.fn();
+ const mockRefresh = jest.fn();
+
+ beforeEach(() => {
+ // 初始化模拟函数返回值
+ mockUseAppDispatch.mockReturnValue(mockDispatch);
+ mockUseNavigate.mockReturnValue(mockNavigate);
+ mockUseSelector.mockImplementation((selector) => selector({ user: { userName: '' } }));
+
+ // 默认模拟 useApi 返回正常状态
+ mockUseApi.mockReturnValue({
+ data: { token: 'mock-token' },
+ loading: false,
+ error: null,
+ refresh: mockRefresh,
+ });
+ });
+
+ afterEach(() => {
+ jest.clearAllMocks();
+ });
+
+ // 测试 1: 基础渲染
+ it('渲染所有输入框和按钮', () => {
+ render(<Login />);
+ expect(screen.getByPlaceholderText('Enter your email')).toBeInTheDocument();
+ expect(screen.getByPlaceholderText('Enter your password')).toBeInTheDocument();
+ expect(screen.getByText('登录')).toBeInTheDocument();
+ expect(screen.getByText('注册')).toBeInTheDocument();
+ expect(screen.getByText('忘记密码')).toBeInTheDocument();
+ });
+
+ // 测试 2: 登录成功流程
+ it('点击登录按钮触发API请求、Redux更新和导航', async () => {
+ // 模拟 API 返回有效数据
+ mockRefresh.mockResolvedValue({ token: 'mock-token' }); // 关键:必须返回 Promise
+ mockUseApi.mockReturnValue({
+ data: { token: 'mock-token' },
+ loading: false,
+ error: null,
+ refresh: mockRefresh,
+ });
+
+ render(<Login />);
+
+ fireEvent.click(screen.getByText('登录'));
+
+ await waitFor(() => {
+ // 验证 dispatch 调用
+ expect(mockDispatch).toHaveBeenCalledWith({
+ type: 'user/login',
+ payload: { token: 'mock-token' },
+ });
+ });
+ });
+
+
+ });
\ No newline at end of file