Files
PicAnalysis/frontend/mcp-full-test.cjs

321 lines
8.8 KiB
JavaScript
Raw Normal View History

/**
* MCP Playwright 完整测试
* 测试所有页面并检查
* 1. 页面加载正常
* 2. 控制台无错误
* 3. UI 展示正常
* 4. 基本功能可用
*/
const { chromium } = require('playwright');
const fs = require('fs');
// 测试配置
const BASE_URL = 'http://localhost:3000';
const SCREENSHOT_DIR = 'screenshots/mcp-full-test';
const TEST_USER = {
username: 'testuser',
password: 'Password123@'
};
// 创建截图目录
if (!fs.existsSync(SCREENSHOT_DIR)) {
fs.mkdirSync(SCREENSHOT_DIR, { recursive: true });
}
// 测试结果收集
const testResults = {
timestamp: new Date().toISOString(),
pages: [],
summary: {
total: 0,
passed: 0,
failed: 0,
errors: []
}
};
/**
* 测试单个页面
*/
async function testPage(page, pageInfo) {
const pageResult = {
name: pageInfo.name,
url: pageInfo.url,
passed: true,
errors: [],
warnings: [],
screenshots: []
};
console.log(`\n📄 测试页面: ${pageInfo.name}`);
console.log(` URL: ${pageInfo.url}`);
try {
// 监听控制台消息
const consoleMessages = [];
page.on('console', msg => {
const type = msg.type();
const text = msg.text();
if (type === 'error') {
consoleMessages.push({ type, text });
pageResult.errors.push(`[Console Error] ${text}`);
} else if (type === 'warning') {
pageResult.warnings.push(`[Console Warning] ${text}`);
}
});
// 监听页面错误
const pageErrors = [];
page.on('pageerror', error => {
pageErrors.push(error.toString());
pageResult.errors.push(`[Page Error] ${error.message}`);
});
// 导航到页面
console.log(` ⏳ 正在加载页面...`);
await page.goto(pageInfo.url, {
waitUntil: 'networkidle',
timeout: 30000
});
// 等待页面稳定
await page.waitForTimeout(2000);
// 检查页面标题
const title = await page.title();
console.log(` 📋 页面标题: ${title}`);
// 截图 - 完整页面
const fullScreenshot = `${SCREENSHOT_DIR}/${pageInfo.name}-full.png`;
await page.screenshot({
path: fullScreenshot,
fullPage: true
});
pageResult.screenshots.push(fullScreenshot);
console.log(` 📸 完整截图: ${fullScreenshot}`);
// 截图 - 视口
const viewportScreenshot = `${SCREENSHOT_DIR}/${pageInfo.name}-viewport.png`;
await page.screenshot({
path: viewportScreenshot,
fullPage: false
});
pageResult.screenshots.push(viewportScreenshot);
// 检查页面基本信息
const bodyText = await page.evaluate(() => document.body.innerText);
const hasContent = bodyText.length > 100;
console.log(` 📝 内容长度: ${bodyText.length} 字符`);
if (!hasContent) {
pageResult.errors.push('页面内容过少,可能未正常加载');
pageResult.passed = false;
}
// 检查是否有死链
const brokenLinks = await page.evaluate(() => {
const links = Array.from(document.querySelectorAll('a[href]'));
return links.filter(link => {
const href = link.getAttribute('href');
return href && href.startsWith('http') && !href.includes(window.location.hostname);
}).length;
});
if (brokenLinks > 0) {
pageResult.warnings.push(`发现 ${brokenLinks} 个外部链接`);
}
// 检查响应式设计
const mobileViewport = { width: 375, height: 667 };
await page.setViewportSize(mobileViewport);
await page.waitForTimeout(500);
const mobileScreenshot = `${SCREENSHOT_DIR}/${pageInfo.name}-mobile.png`;
await page.screenshot({ path: mobileScreenshot });
pageResult.screenshots.push(mobileScreenshot);
console.log(` 📱 移动端截图: ${mobileScreenshot}`);
// 恢复桌面视口
await page.setViewportSize({ width: 1280, height: 720 });
// 执行页面特定测试
if (pageInfo.test) {
console.log(` 🔧 执行页面特定测试...`);
await pageInfo.test(page, pageResult);
}
// 统计错误
if (pageResult.errors.length > 0) {
pageResult.passed = false;
console.log(` ❌ 发现 ${pageResult.errors.length} 个错误:`);
pageResult.errors.forEach(err => console.log(` - ${err}`));
}
if (pageResult.warnings.length > 0) {
console.log(` ⚠️ 发现 ${pageResult.warnings.length} 个警告:`);
pageResult.warnings.slice(0, 3).forEach(warn => console.log(` - ${warn}`));
}
if (pageResult.passed) {
console.log(` ✅ 页面测试通过`);
} else {
console.log(` ❌ 页面测试失败`);
}
} catch (error) {
pageResult.passed = false;
pageResult.errors.push(`测试异常: ${error.message}`);
console.log(` ❌ 测试失败: ${error.message}`);
}
return pageResult;
}
/**
* 主测试流程
*/
async function runTests() {
console.log('🎭 MCP Playwright 完整测试开始');
console.log('='.repeat(60));
console.log(`基础URL: ${BASE_URL}`);
console.log(`截图目录: ${SCREENSHOT_DIR}`);
console.log('='.repeat(60));
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 pagesToTest = [
{
name: '01-homepage',
url: `${BASE_URL}/`,
description: '首页/登录页'
},
{
name: '02-dashboard',
url: `${BASE_URL}/dashboard`,
description: '仪表盘'
},
{
name: '03-documents',
url: `${BASE_URL}/documents`,
description: '文档管理'
},
{
name: '04-todos',
url: `${BASE_URL}/todos`,
description: '待办事项'
},
{
name: '05-images',
url: `${BASE_URL}/images`,
description: '图片管理'
}
];
// 首先尝试登录
console.log('\n🔐 尝试登录...');
try {
await page.goto(`${BASE_URL}/`, { waitUntil: 'networkidle' });
await page.waitForTimeout(1000);
// 查找并填写登录表单
const usernameInput = page.locator('input[type="text"]').first();
const passwordInput = page.locator('input[type="password"]').first();
const loginButton = page.locator('button').filter({ hasText: /登录|Login/i }).first();
if (await usernameInput.count() > 0 && await passwordInput.count() > 0) {
await usernameInput.fill(TEST_USER.username);
await passwordInput.fill(TEST_USER.password);
if (await loginButton.count() > 0) {
await loginButton.click();
console.log(' ✅ 登录表单已提交');
await page.waitForTimeout(2000);
} else {
console.log(' ⚠️ 未找到登录按钮');
}
} else {
console.log(' 未找到登录表单,可能已经登录');
}
} catch (error) {
console.log(` ⚠️ 登录过程异常: ${error.message}`);
}
// 测试每个页面
for (const pageInfo of pagesToTest) {
const result = await testPage(page, pageInfo);
testResults.pages.push(result);
testResults.summary.total++;
if (result.passed) {
testResults.summary.passed++;
} else {
testResults.summary.failed++;
testResults.summary.errors.push(...result.errors);
}
// 页面间等待
await page.waitForTimeout(1000);
}
// 生成测试报告
console.log('\n' + '='.repeat(60));
console.log('📊 测试汇总');
console.log('='.repeat(60));
testResults.pages.forEach(page => {
const status = page.passed ? '✅' : '❌';
console.log(`${status} ${page.name} - ${page.errors.length} 错误, ${page.warnings.length} 警告`);
});
console.log('\n总计:');
console.log(` 总页面数: ${testResults.summary.total}`);
console.log(` 通过: ${testResults.summary.passed}`);
console.log(` 失败: ${testResults.summary.failed}`);
console.log(` 通过率: ${((testResults.summary.passed / testResults.summary.total) * 100).toFixed(1)}%`);
if (testResults.summary.errors.length > 0) {
console.log('\n⚠ 所有错误:');
testResults.summary.errors.forEach((err, i) => {
console.log(` ${i + 1}. ${err}`);
});
}
console.log('\n📸 所有截图保存在:', SCREENSHOT_DIR);
// 保存测试结果
const resultsPath = 'test-results.json';
fs.writeFileSync(resultsPath, JSON.stringify(testResults, null, 2));
console.log('📄 测试结果已保存到:', resultsPath);
// 等待用户查看
console.log('\n⏳ 5秒后关闭浏览器...');
await page.waitForTimeout(5000);
await browser.close();
console.log('\n🎉 测试完成!');
return testResults;
}
// 运行测试
runTests()
.then(results => {
const exitCode = results.summary.failed > 0 ? 1 : 0;
process.exit(exitCode);
})
.catch(error => {
console.error('❌ 测试运行失败:', error);
process.exit(1);
});