280 lines
8.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 测试模式
**分析日期:** 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 的关键区域。