Files
PicAnalysis/frontend/e2e/complete-flow.spec.ts
wjl 1a0ebde95d feat: 初始化 PicAnalysis 项目
完整的前后端图片分析应用,包含:
- 后端:Express + Prisma + SQLite,101个单元测试全部通过
- 前端:React + TypeScript + Vite,47个单元测试,89.73%覆盖率
- E2E测试:Playwright 测试套件
- MCP集成:Playwright MCP配置完成并测试通过

功能模块:
- 用户认证(JWT)
- 文档管理(CRUD)
- 待办管理(三态工作流)
- 图片管理(上传、截图、OCR)

测试覆盖:
- 后端单元测试:101/101 
- 前端单元测试:47/47 
- E2E测试:通过 
- MCP Playwright测试:通过 

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 20:10:11 +08:00

245 lines
8.4 KiB
TypeScript

import { test, expect } from '@playwright/test';
test.describe('前端应用完整流程测试', () => {
test.beforeEach(async ({ page }) => {
// Mock API 响应
await page.route('**/api/auth/login', route => {
route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({
success: true,
data: {
token: 'test-token-abc123',
user: {
id: '1',
username: 'testuser',
email: 'test@example.com',
created_at: '2024-01-01',
updated_at: '2024-01-01'
}
}
})
});
});
await page.route('**/api/documents**', route => {
route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({
success: true,
data: [
{
id: '1',
title: '示例文档',
content: '这是一个示例文档内容,用于演示文档管理功能。',
created_at: '2024-01-01T00:00:00Z',
updated_at: '2024-01-01T00:00:00Z',
user_id: '1',
category_id: null
}
],
count: 1
})
});
});
await page.route('**/api/todos**', route => {
route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({
success: true,
data: [
{
id: '1',
title: '完成项目文档',
description: '编写完整的项目文档',
priority: 'high',
status: 'pending',
created_at: '2024-01-01T00:00:00Z',
updated_at: '2024-01-01T00:00:00Z',
user_id: '1',
document_id: null,
category_id: null,
due_date: null,
completed_at: null,
confirmed_at: null
}
]
})
});
});
await page.route('**/api/todos/pending', route => {
route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({
success: true,
data: [
{
id: '1',
title: '完成项目文档',
description: '编写完整的项目文档',
priority: 'high',
status: 'pending',
created_at: '2024-01-01T00:00:00Z',
updated_at: '2024-01-01T00:00:00Z',
user_id: '1',
document_id: null,
category_id: null,
due_date: null,
completed_at: null,
confirmed_at: null
}
]
})
});
});
await page.route('**/api/todos/completed', route => {
route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({
success: true,
data: []
})
});
});
await page.route('**/api/images**', route => {
route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({
success: true,
data: [
{
id: '1',
file_path: 'https://via.placeholder.com/300',
file_size: 102400,
mime_type: 'image/jpeg',
ocr_result: '这是 OCR 识别的文本结果',
ocr_confidence: 0.95,
processing_status: 'completed',
quality_score: 0.9,
error_message: null,
created_at: '2024-01-01T00:00:00Z',
updated_at: '2024-01-01T00:00:00Z',
user_id: '1',
document_id: null
}
],
count: 1
})
});
});
await page.route('**/api/images/pending', route => {
route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({
success: true,
data: []
})
});
});
});
test('完整用户流程:登录 -> 浏览所有页面', async ({ page }) => {
console.log('\n═════════════════════════════════════════════════════');
console.log('🚀 开始完整用户流程测试');
console.log('═════════════════════════════════════════════════════\n');
// 1. 访问登录页面
console.log('📄 步骤 1: 访问登录页面');
await page.goto('http://localhost:3000', { waitUntil: 'networkidle' });
await page.screenshot({ path: 'screenshots/01-login.png' });
console.log('✅ 登录页面截图完成\n');
// 2. 填写登录表单
console.log('🔐 步骤 2: 填写登录表单');
await page.fill('input[label="用户名"]', 'testuser');
await page.fill('input[label="密码"]', 'Password123@');
await page.screenshot({ path: 'screenshots/02-login-filled.png' });
console.log('✅ 表单填写完成\n');
// 3. 点击登录按钮
console.log('🔑 步骤 3: 点击登录按钮');
await page.click('button[type="submit"]');
// 等待跳转到仪表盘
await page.waitForURL('**/dashboard', { timeout: 10000 });
await page.waitForLoadState('networkidle');
await page.screenshot({ path: 'screenshots/03-dashboard.png', fullPage: true });
console.log('✅ 登录成功,仪表盘截图完成\n');
// 4. 访问文档页面
console.log('📄 步骤 4: 访问文档页面');
await page.click('text=文档');
await page.waitForLoadState('networkidle');
await page.screenshot({ path: 'screenshots/04-documents.png', fullPage: true });
console.log('✅ 文档页面截图完成\n');
// 5. 访问待办页面
console.log('✅ 步骤 5: 访问待办页面');
await page.click('text=待办');
await page.waitForLoadState('networkidle');
await page.screenshot({ path: 'screenshots/05-todos.png', fullPage: true });
console.log('✅ 待办页面截图完成\n');
// 6. 访问图片页面
console.log('🖼️ 步骤 6: 访问图片页面');
await page.click('text=图片');
await page.waitForLoadState('networkidle');
await page.screenshot({ path: 'screenshots/06-images.png', fullPage: true });
console.log('✅ 图片页面截图完成\n');
console.log('═════════════════════════════════════════════════════');
console.log('🎉 所有测试完成!');
console.log('═════════════════════════════════════════════════════');
console.log('\n📁 截图已保存到 screenshots/ 目录:');
console.log(' 1. 01-login.png - 登录页面');
console.log(' 2. 02-login-filled.png - 填写表单');
console.log(' 3. 03-dashboard.png - 仪表盘');
console.log(' 4. 04-documents.png - 文档管理');
console.log(' 5. 05-todos.png - 待办事项');
console.log(' 6. 06-images.png - 图片管理');
console.log('');
});
test('验证页面元素', async ({ page }) => {
// 先登录
await page.goto('http://localhost:3000');
await page.fill('input[label="用户名"]', 'testuser');
await page.fill('input[label="密码"]', 'Password123@');
await page.click('button[type="submit"]');
await page.waitForURL('**/dashboard');
// 验证仪表盘元素
await expect(page.locator('h2')).toContainText('仪表盘');
await expect(page.locator('text=文档总数')).toBeVisible();
await expect(page.locator('text=待办任务')).toBeVisible();
await expect(page.locator('text=已完成')).toBeVisible();
// 访问文档页面
await page.click('text=文档');
await expect(page.locator('h1')).toContainText('文档管理');
await expect(page.locator('text=新建文档')).toBeVisible();
// 访问待办页面
await page.click('text=待办');
await expect(page.locator('h1')).toContainText('待办事项');
await expect(page.locator('text=新建待办')).toBeVisible();
// 访问图片页面
await page.click('text=图片');
await expect(page.locator('h1')).toContainText('图片管理');
await expect(page.locator('text=上传图片')).toBeVisible();
});
});