280 lines
8.0 KiB
Markdown
280 lines
8.0 KiB
Markdown
# 测试模式
|
||
|
||
**分析日期:** 2026-05-07
|
||
|
||
## 测试框架
|
||
|
||
**当前状态:** 未检测到测试基础设施
|
||
|
||
- **运行器:** 未配置(package.json 中无 Jest、Vitest、Playwright 等依赖)
|
||
- **断言库:** 未配置
|
||
- **测试脚本:** 未在 package.json 中定义(仅有 `dev`、`build`、`start`、`lint`)
|
||
|
||
## 测试文件组织
|
||
|
||
**当前:** 无测试文件
|
||
|
||
项目中未发现 `*.test.ts`、`*.test.tsx`、`*.spec.ts`、`*.spec.tsx`、`__tests__/` 目录等标准测试文件结构。
|
||
|
||
## 测试覆盖
|
||
|
||
**要求:** 未强制
|
||
|
||
**影响:**
|
||
- 新增代码(尤其是 API 集成、表单验证、权限逻辑)缺乏自动化验证
|
||
- 技术债风险:`next.config.mjs` 中 `typescript.ignoreBuildErrors: true` 和 `eslint.ignoreDuringBuilds: true`,导致构建时不检查类型和 lint 错误
|
||
- 手动测试依赖性高
|
||
|
||
## 关键需要测试的区域
|
||
|
||
### API 集成层
|
||
**位置:** `lib/api/*.ts`
|
||
|
||
**建议测试:**
|
||
- 认证流程(`emailLogin`、`saveAuthToken`、`logout`)
|
||
- API 请求拦截器(token 注入、过期处理)
|
||
- 响应拦截器(401 处理、重定向)
|
||
- 数据适配器(如 `mapBackendOutfit()` 将后端结构映射到前端类型)
|
||
- 错误处理(`handleApiException`、`handleApiRequest` 的成功/失败路径)
|
||
|
||
**示例测试需求:**
|
||
```typescript
|
||
// 应测试:token 自动注入
|
||
test('请求拦截器应在请求头中添加 Bearer token', () => {
|
||
// 前置条件:localStorage 中有 auth_token
|
||
// 发送 API 请求
|
||
// 验证:Authorization 头包含 "Bearer <token>"
|
||
})
|
||
|
||
// 应测试:401 处理
|
||
test('响应拦截器应在收到 401 时清除 token 并重定向到登录', () => {
|
||
// 前置条件:发送请求后服务器返回 401
|
||
// 验证:localStorage 中 auth_token 被移除
|
||
// 验证:浏览器重定向到 /login
|
||
})
|
||
|
||
// 应测试:数据适配
|
||
test('mapBackendOutfit 应正确转换后端服装数据', () => {
|
||
const backendData = { id: 1, name: '测试服装', image_url: '...' }
|
||
const result = mapBackendOutfit(backendData)
|
||
expect(result).toHaveProperty('imageUrl') // 字段映射
|
||
expect(result.id).toBe('1') // 类型转换
|
||
})
|
||
```
|
||
|
||
### 权限控制
|
||
**位置:** `lib/permissions.ts`
|
||
|
||
**建议测试:**
|
||
- `hasPermission(module)` 根据用户角色返回正确的权限
|
||
- `getUserRole()` 从 localStorage 获取当前角色
|
||
- `getModuleFromPath(pathname)` 正确提取路径中的模块
|
||
- `hasPathPermission(pathname)` 组合权限检查
|
||
|
||
**示例测试需求:**
|
||
```typescript
|
||
test('超级管理员应有所有模块的权限', () => {
|
||
// 前置:localStorage.user_role = '超级管理员'
|
||
// 验证:hasPermission('users') === true
|
||
// 验证:hasPermission('ai-model') === true
|
||
// 等等所有模块
|
||
})
|
||
|
||
test('内容管理员应无权限访问用户管理', () => {
|
||
// 前置:localStorage.user_role = '内容管理员'
|
||
// 验证:hasPermission('users') === false
|
||
// 验证:hasPermission('outfits') === true
|
||
})
|
||
```
|
||
|
||
### 表单验证与提交
|
||
**位置:** `components/*/add-*-dialog.tsx`、`app/*/page.tsx`
|
||
|
||
**当前模式:**
|
||
- 使用 `useState` 管理表单状态
|
||
- 基本的非空检查(如 `if (!formData.name || !formData.description)` 在 `add-achievement-dialog.tsx`)
|
||
- 客户端验证不完整
|
||
|
||
**建议测试:**
|
||
- 必填字段验证(空值拒绝)
|
||
- 表单提交成功调用正确的 API
|
||
- 提交过程中加载状态变化(`isSubmitting`)
|
||
- 表单重置(关闭后清空状态)
|
||
- 错误显示(API 失败时显示 toast)
|
||
|
||
**示例测试需求:**
|
||
```typescript
|
||
test('添加服装对话框应在名称为空时禁用提交', () => {
|
||
// 渲染 AddOutfitDialog
|
||
// 验证:提交按钮禁用状态
|
||
})
|
||
|
||
test('提交表单应调用 createOutfit API', () => {
|
||
// 填写表单字段
|
||
// 点击提交
|
||
// 验证:createOutfit 被调用,参数正确
|
||
})
|
||
```
|
||
|
||
### 组件交互
|
||
**位置:** `components/`
|
||
|
||
**建议测试:**
|
||
- 对话框打开/关闭状态
|
||
- 模态框表单的步骤导航(`step` 状态变化)
|
||
- 确认对话框的确认/取消操作
|
||
- 列表分页和搜索
|
||
|
||
**示例测试需求:**
|
||
```typescript
|
||
test('AddOutfitDialog 应在提交后关闭', () => {
|
||
// 渲染对话框
|
||
// 填写并提交表单
|
||
// 验证:对话框关闭(open === false)
|
||
})
|
||
|
||
test('多步表单应在点击"下一步"时更新步骤', () => {
|
||
// 验证:初始 step === 1
|
||
// 点击"下一步"按钮
|
||
// 验证:step === 2
|
||
})
|
||
```
|
||
|
||
### 中间件和路由保护
|
||
**位置:** `middleware.ts`
|
||
|
||
**建议测试:**
|
||
- 无 token 访问受保护路由时重定向到 `/login`
|
||
- 有 token 时允许访问受保护路由
|
||
- 公共路由(登录、注册)不需要 token
|
||
|
||
**示例测试需求:**
|
||
```typescript
|
||
test('中间件应将无 token 的请求重定向到登录', () => {
|
||
// 模拟请求:GET /outfits,无 auth_token cookie
|
||
// 验证:重定向到 /login?callbackUrl=/outfits
|
||
})
|
||
|
||
test('中间件应允许有 token 的请求', () => {
|
||
// 模拟请求:GET /users,包含有效 auth_token cookie
|
||
// 验证:通过,继续处理
|
||
})
|
||
```
|
||
|
||
## 建议的测试设置
|
||
|
||
### 推荐框架组合
|
||
|
||
**单元/集成测试:**
|
||
- **运行器:** Vitest(与 Next.js 15 兼容,开发体验优于 Jest)
|
||
- **断言:** Vitest 内置(或 @testing-library/jest-dom)
|
||
- **Mock 库:** vitest 的 `vi` 模块或 `@testing-library/react`
|
||
|
||
**E2E 测试(可选):**
|
||
- **框架:** Playwright 或 Cypress
|
||
- **用途:** 完整登录流、权限控制、多步表单
|
||
|
||
### 安装建议
|
||
|
||
```bash
|
||
# 安装 Vitest 和相关工具
|
||
npm install -D vitest @vitest/ui @testing-library/react @testing-library/jest-dom
|
||
|
||
# 创建配置文件 vitest.config.ts
|
||
```
|
||
|
||
### 最小化配置示例
|
||
|
||
```typescript
|
||
// vitest.config.ts
|
||
import { defineConfig } from 'vitest/config'
|
||
import react from '@vitejs/plugin-react'
|
||
import path from 'path'
|
||
|
||
export default defineConfig({
|
||
plugins: [react()],
|
||
test: {
|
||
globals: true,
|
||
environment: 'jsdom',
|
||
setupFiles: ['./test/setup.ts'],
|
||
},
|
||
resolve: {
|
||
alias: {
|
||
'@': path.resolve(__dirname, '.'),
|
||
},
|
||
},
|
||
})
|
||
|
||
// test/setup.ts
|
||
import '@testing-library/jest-dom'
|
||
```
|
||
|
||
### package.json 脚本建议
|
||
|
||
```json
|
||
{
|
||
"scripts": {
|
||
"test": "vitest",
|
||
"test:ui": "vitest --ui",
|
||
"test:coverage": "vitest --coverage",
|
||
"test:run": "vitest run"
|
||
}
|
||
}
|
||
```
|
||
|
||
## 测试文件结构建议
|
||
|
||
```
|
||
project-root/
|
||
├── lib/
|
||
│ ├── api/
|
||
│ │ ├── auth.ts
|
||
│ │ ├── auth.test.ts # API 认证测试
|
||
│ │ ├── outfits.ts
|
||
│ │ ├── outfits.test.ts # API 服装测试
|
||
│ │ └── ...
|
||
│ ├── permissions.ts
|
||
│ └── permissions.test.ts # 权限逻辑测试
|
||
├── components/
|
||
│ ├── add-outfit-dialog.tsx
|
||
│ ├── add-outfit-dialog.test.tsx # 组件交互测试
|
||
│ └── ...
|
||
├── app/
|
||
│ ├── login/
|
||
│ │ ├── page.tsx
|
||
│ │ └── page.test.tsx # 登录页测试
|
||
│ └── ...
|
||
├── test/
|
||
│ ├── setup.ts # 测试环境初始化
|
||
│ ├── mocks/
|
||
│ │ ├── handlers.ts # MSW 请求拦截器
|
||
│ │ └── server.ts # MSW 服务器配置
|
||
│ └── fixtures/
|
||
│ ├── auth.fixture.ts # 认证数据 fixtures
|
||
│ └── outfits.fixture.ts # 服装数据 fixtures
|
||
└── vitest.config.ts
|
||
```
|
||
|
||
## 当前缺失的覆盖范围
|
||
|
||
**高优先级(生产关键):**
|
||
- ✗ API 集成和数据适配
|
||
- ✗ 认证流程(登录、token 管理、登出)
|
||
- ✗ 权限检查和路由保护
|
||
- ✗ 表单验证和提交
|
||
|
||
**中优先级(功能完整性):**
|
||
- ✗ 错误处理和用户通知
|
||
- ✗ 组件交互(对话框、模态框)
|
||
- ✗ 列表管理(分页、搜索)
|
||
|
||
**低优先级(UX 细节):**
|
||
- ✗ 样式和响应性
|
||
- ✗ 无障碍访问 (a11y)
|
||
|
||
---
|
||
|
||
*测试分析日期:2026-05-07*
|
||
|
||
**关键建议:** 该项目缺乏测试基础设施,强烈建议在新增核心功能(特别是认证、权限、API 集成)时同步添加测试。考虑从 API 层和权限控制开始,这些是最容易产生 bug 的关键区域。
|