Files
PicAnalysis/frontend/final-test.cjs
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

153 lines
4.0 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 最终 MCP Playwright 测试 - 确保页面完全加载
*/
const { chromium } = require('playwright');
const fs = require('fs');
const BASE_URL = 'http://localhost:3000';
const SCREENSHOT_DIR = 'screenshots/final-test';
if (!fs.existsSync(SCREENSHOT_DIR)) {
fs.mkdirSync(SCREENSHOT_DIR, { recursive: true });
}
(async () => {
console.log('🎭 开始最终测试...\n');
const browser = await chromium.launch({
headless: false,
channel: 'chrome'
});
const context = await browser.newContext({
viewport: { width: 1280, height: 720 }
});
const page = await context.newPage();
// 监听控制台
const errors = [];
page.on('console', msg => {
if (msg.type() === 'error') {
errors.push(`[Console] ${msg.text()}`);
}
});
page.on('pageerror', error => {
errors.push(`[Page] ${error.message}`);
});
const pages = [
{ name: '01-homepage', url: '/', title: '首页' },
{ name: '02-dashboard', url: '/dashboard', title: '仪表盘' },
{ name: '03-documents', url: '/documents', title: '文档管理' },
{ name: '04-todos', url: '/todos', title: '待办事项' },
{ name: '05-images', url: '/images', title: '图片管理' }
];
const results = [];
for (const pageInfo of pages) {
console.log(`📄 测试: ${pageInfo.title} (${pageInfo.url})`);
try {
// 导航到页面
await page.goto(`${BASE_URL}${pageInfo.url}`, {
waitUntil: 'networkidle',
timeout: 30000
});
// 等待 React 渲染完成
await page.waitForTimeout(2000);
// 等待关键元素出现
try {
await page.waitForSelector('body', { timeout: 5000 });
} catch (e) {
// body 应该总是存在,忽略错误
}
// 获取页面内容
const pageInfo_data = await page.evaluate(() => {
const root = document.getElementById('root');
return {
hasRoot: !!root,
rootHasChildren: root ? root.children.length > 0 : false,
bodyText: document.body.innerText.substring(0, 200),
title: document.title
};
});
// 截图
const screenshotPath = `${SCREENSHOT_DIR}/${pageInfo.name}.png`;
await page.screenshot({
path: screenshotPath,
fullPage: true
});
console.log(` ✅ 截图: ${screenshotPath}`);
console.log(` 📋 内容: ${pageInfo_data.bodyText.substring(0, 50)}...`);
results.push({
page: pageInfo.title,
url: pageInfo.url,
success: true,
hasContent: pageInfo_data.bodyText.length > 50,
errors: []
});
} catch (error) {
console.error(` ❌ 错误: ${error.message}`);
results.push({
page: pageInfo.title,
url: pageInfo.url,
success: false,
hasContent: false,
errors: [error.message]
});
}
console.log('');
}
// 生成报告
console.log('='.repeat(60));
console.log('📊 测试结果汇总');
console.log('='.repeat(60));
results.forEach(r => {
const status = r.success && r.hasContent ? '✅' : '❌';
const content = r.hasContent ? '有内容' : '无内容';
console.log(`${status} ${r.page} - ${content}`);
if (r.errors.length > 0) {
r.errors.forEach(e => console.log(` 错误: ${e}`));
}
});
const passed = results.filter(r => r.success && r.hasContent).length;
const total = results.length;
console.log(`\n总计: ${passed}/${total} 通过 (${((passed/total)*100).toFixed(0)}%)`);
if (errors.length > 0) {
console.log('\n⚠ 控制台错误:');
errors.forEach(e => console.log(` - ${e}`));
} else {
console.log('\n✅ 无控制台错误');
}
console.log(`\n📸 截图保存在: ${SCREENSHOT_DIR}/`);
// 保存结果
fs.writeFileSync(
'final-test-results.json',
JSON.stringify({ results, errors }, null, 2)
);
console.log('\n⏳ 3秒后关闭...');
await page.waitForTimeout(3000);
await browser.close();
console.log('\n🎉 测试完成!');
})();