完整的前后端图片分析应用,包含: - 后端: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>
177 lines
5.1 KiB
JavaScript
177 lines
5.1 KiB
JavaScript
const playwright = require('playwright');
|
||
|
||
(async () => {
|
||
console.log('🚀 启动 Playwright 测试...\n');
|
||
|
||
const browser = await playwright.chromium.launch({
|
||
headless: false,
|
||
slowMo: 1000
|
||
});
|
||
|
||
const context = await browser.newContext();
|
||
const page = await context.newPage();
|
||
|
||
// 模拟 API 响应
|
||
await page.route('**/api/auth/login', route => {
|
||
route.fulfill({
|
||
status: 200,
|
||
contentType: 'application/json',
|
||
body: JSON.stringify({
|
||
success: true,
|
||
data: {
|
||
token: 'test-token',
|
||
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: []
|
||
})
|
||
});
|
||
});
|
||
|
||
try {
|
||
// 1. 访问登录页面
|
||
console.log('📄 访问登录页面...');
|
||
await page.goto('http://localhost:3000');
|
||
await page.waitForLoadState('networkidle');
|
||
await page.screenshot({ path: 'screenshots/01-login.png' });
|
||
console.log('✅ 登录页面截图完成');
|
||
|
||
// 2. 执行登录
|
||
console.log('\n🔐 执行登录操作...');
|
||
await page.fill('input[label="用户名"]', 'testuser');
|
||
await page.fill('input[label="密码"]', 'password123');
|
||
await page.click('button[type="submit"]');
|
||
|
||
// 等待跳转
|
||
await page.waitForURL('**/dashboard', { timeout: 5000 });
|
||
await page.waitForLoadState('networkidle');
|
||
await page.screenshot({ path: 'screenshots/02-dashboard.png', fullPage: true });
|
||
console.log('✅ 登录成功,仪表盘截图完成');
|
||
|
||
// 3. 访问文档页面
|
||
console.log('\n📄 访问文档页面...');
|
||
await page.click('text=文档');
|
||
await page.waitForLoadState('networkidle');
|
||
await page.screenshot({ path: 'screenshots/03-documents.png', fullPage: true });
|
||
console.log('✅ 文档页面截图完成');
|
||
|
||
// 4. 访问待办页面
|
||
console.log('\n📋 访问待办页面...');
|
||
await page.click('text=待办');
|
||
await page.waitForLoadState('networkidle');
|
||
await page.screenshot({ path: 'screenshots/04-todos.png', fullPage: true });
|
||
console.log('✅ 待办页面截图完成');
|
||
|
||
// 5. 访问图片页面
|
||
console.log('\n🖼️ 访问图片页面...');
|
||
await page.click('text=图片');
|
||
await page.waitForLoadState('networkidle');
|
||
await page.screenshot({ path: 'screenshots/05-images.png', fullPage: true });
|
||
console.log('✅ 图片页面截图完成');
|
||
|
||
console.log('\n✨ 所有测试和截图完成!');
|
||
console.log('\n📁 截图已保存到 screenshots/ 目录');
|
||
console.log(' - 01-login.png: 登录页面');
|
||
console.log(' - 02-dashboard.png: 仪表盘');
|
||
console.log(' - 03-documents.png: 文档管理');
|
||
console.log(' - 04-todos.png: 待办事项');
|
||
console.log(' - 05-images.png: 图片管理');
|
||
|
||
} catch (error) {
|
||
console.error('❌ 测试过程中出错:', error.message);
|
||
} finally {
|
||
await browser.close();
|
||
}
|
||
})();
|