Files
PicAnalysis/frontend/complete-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

200 lines
5.5 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/complete-test';
const TEST_USER = {
username: 'testuser',
password: 'Password123@'
};
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}`);
});
console.log('🔐 步骤 1: 登录');
console.log(' 访问登录页面...');
await page.goto(`${BASE_URL}/`, {
waitUntil: 'networkidle',
timeout: 30000
});
await page.waitForTimeout(1000);
// 截图登录页
await page.screenshot({
path: `${SCREENSHOT_DIR}/00-login.png`,
fullPage: true
});
console.log(' ✅ 登录页面截图');
// 尝试登录
console.log(' 填写登录信息...');
try {
const usernameInput = page.locator('input[type="text"]').first();
const passwordInput = page.locator('input[type="password"]').first();
await usernameInput.fill(TEST_USER.username);
await passwordInput.fill(TEST_USER.password);
console.log(' 点击登录按钮...');
const loginButton = page.locator('button').filter({ hasText: /登录|Login/i }).first();
await loginButton.click();
// 等待导航
console.log(' 等待登录完成...');
await page.waitForTimeout(3000);
// 截图登录后
await page.screenshot({
path: `${SCREENSHOT_DIR}/00-after-login.png`,
fullPage: true
});
console.log(' ✅ 登录后截图');
} catch (error) {
console.log(` ⚠️ 登录过程: ${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(`\n📄 测试: ${pageInfo.title} (${pageInfo.url})`);
try {
await page.goto(`${BASE_URL}${pageInfo.url}`, {
waitUntil: 'networkidle',
timeout: 30000
});
// 等待页面渲染
await page.waitForTimeout(2000);
// 获取页面信息
const pageInfo_data = await page.evaluate(() => {
return {
title: document.title,
url: window.location.pathname,
bodyText: document.body.innerText.substring(0, 300),
hasLayout: !!document.querySelector('[class*="layout"]'),
hasSidebar: !!document.querySelector('[class*="sidebar"]'),
cardCount: document.querySelectorAll('[class*="card"]').length
};
});
// 截图
const screenshotPath = `${SCREENSHOT_DIR}/${pageInfo.name}.png`;
await page.screenshot({
path: screenshotPath,
fullPage: true
});
console.log(` ✅ 截图: ${screenshotPath}`);
console.log(` 📋 URL: ${pageInfo_data.url}`);
console.log(` 📝 内容长度: ${pageInfo_data.bodyText.length} 字符`);
console.log(` 🎴 卡片数: ${pageInfo_data.cardCount}`);
console.log(` 📐 有布局: ${pageInfo_data.hasLayout ? '是' : '否'}`);
results.push({
page: pageInfo.title,
url: pageInfo.url,
success: true,
hasContent: pageInfo_data.bodyText.length > 100,
contentPreview: pageInfo_data.bodyText.substring(0, 100).replace(/\n/g, ' ')
});
} catch (error) {
console.error(` ❌ 错误: ${error.message}`);
results.push({
page: pageInfo.title,
url: pageInfo.url,
success: false,
hasContent: false,
error: error.message
});
}
}
// 生成报告
console.log('\n' + '='.repeat(60));
console.log('📊 测试结果汇总');
console.log('='.repeat(60));
results.forEach(r => {
const status = r.success && r.hasContent ? '✅' : '⚠️';
console.log(`${status} ${r.page}`);
console.log(` URL: ${r.url}`);
if (r.contentPreview) {
console.log(` 内容: ${r.contentPreview}...`);
}
if (r.error) {
console.log(` 错误: ${r.error}`);
}
console.log('');
});
const passed = results.filter(r => r.success && r.hasContent).length;
const total = results.length;
console.log(`总计: ${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(
'complete-test-results.json',
JSON.stringify({ results, errors }, null, 2)
);
console.log('\n⏳ 5秒后关闭浏览器...');
await page.waitForTimeout(5000);
await browser.close();
console.log('\n🎉 测试完成!');
})();