添加测试配置及登陆部分的测试

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