160 lines
5.1 KiB
JavaScript
160 lines
5.1 KiB
JavaScript
|
|
// ==================== 浏览器端到端测试 ====================
|
||
|
|
|
||
|
|
import puppeteer from 'puppeteer-core';
|
||
|
|
import http from 'http';
|
||
|
|
import fs from 'fs';
|
||
|
|
import path from 'path';
|
||
|
|
|
||
|
|
// 简单HTTP服务器
|
||
|
|
function startServer(port = 8765) {
|
||
|
|
const mimeTypes = {
|
||
|
|
'.html': 'text/html',
|
||
|
|
'.js': 'application/javascript',
|
||
|
|
'.json': 'application/json',
|
||
|
|
'.css': 'text/css',
|
||
|
|
};
|
||
|
|
|
||
|
|
const server = http.createServer((req, res) => {
|
||
|
|
let filePath = '.' + (req.url === '/' ? '/index.html' : req.url);
|
||
|
|
const ext = path.extname(filePath).toLowerCase();
|
||
|
|
const contentType = mimeTypes[ext] || 'application/octet-stream';
|
||
|
|
|
||
|
|
fs.readFile(filePath, (err, content) => {
|
||
|
|
if (err) {
|
||
|
|
res.writeHead(404);
|
||
|
|
res.end('Not found');
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
res.writeHead(200, { 'Content-Type': contentType });
|
||
|
|
res.end(content);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
return new Promise((resolve) => {
|
||
|
|
server.listen(port, () => {
|
||
|
|
console.log(`Server running at http://localhost:${port}`);
|
||
|
|
resolve(server);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
async function runBrowserTest() {
|
||
|
|
const server = await startServer(8765);
|
||
|
|
|
||
|
|
const browser = await puppeteer.launch({
|
||
|
|
headless: true,
|
||
|
|
executablePath: '/usr/bin/chromium-browser',
|
||
|
|
args: ['--no-sandbox', '--disable-setuid-sandbox'],
|
||
|
|
});
|
||
|
|
|
||
|
|
const page = await browser.newPage();
|
||
|
|
const errors = [];
|
||
|
|
const logs = [];
|
||
|
|
|
||
|
|
page.on('pageerror', (err) => {
|
||
|
|
console.error('Page error:', err.message);
|
||
|
|
errors.push(err.message);
|
||
|
|
});
|
||
|
|
|
||
|
|
page.on('console', (msg) => {
|
||
|
|
const text = msg.text();
|
||
|
|
logs.push(text);
|
||
|
|
if (msg.type() === 'error') {
|
||
|
|
console.error('Console error:', text);
|
||
|
|
errors.push(text);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
page.on('response', (response) => {
|
||
|
|
if (response.status() === 404) {
|
||
|
|
console.error('404 Not Found:', response.url());
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
try {
|
||
|
|
console.log('\n=== 浏览器端到端测试 ===');
|
||
|
|
|
||
|
|
// 加载页面
|
||
|
|
console.log('1. 加载页面...');
|
||
|
|
await page.goto('http://localhost:8765', { waitUntil: 'networkidle0', timeout: 10000 });
|
||
|
|
await new Promise(r => setTimeout(r, 500));
|
||
|
|
|
||
|
|
const realErrors = errors.filter(e => !e.includes('favicon.ico') && !e.includes('404'));
|
||
|
|
if (realErrors.length > 0) {
|
||
|
|
throw new Error(`页面加载错误: ${realErrors.join(', ')}`);
|
||
|
|
}
|
||
|
|
console.log(' 页面加载成功,无JS错误');
|
||
|
|
|
||
|
|
// 检查初始状态
|
||
|
|
console.log('2. 检查初始状态...');
|
||
|
|
const age = await page.$eval('#age', el => el.textContent);
|
||
|
|
const money = await page.$eval('#money', el => el.textContent);
|
||
|
|
console.log(` 年龄: ${age}, 银两: ${money}`);
|
||
|
|
|
||
|
|
// 等待一段时间让游戏运行
|
||
|
|
console.log('3. 等待游戏运行5秒...');
|
||
|
|
await new Promise(r => setTimeout(r, 5000));
|
||
|
|
|
||
|
|
// 检查时间是否推进
|
||
|
|
console.log('4. 检查时间推进...');
|
||
|
|
const dayAfter = await page.$eval('#day', el => el.textContent);
|
||
|
|
const yearAfter = await page.$eval('#year', el => el.textContent);
|
||
|
|
console.log(` 年: ${yearAfter}, 天: ${dayAfter}`);
|
||
|
|
|
||
|
|
if (parseInt(dayAfter) <= 0) {
|
||
|
|
throw new Error('时间没有推进');
|
||
|
|
}
|
||
|
|
console.log(' 时间正常推进');
|
||
|
|
|
||
|
|
// 检查职业是否解锁
|
||
|
|
console.log('5. 检查职业面板...');
|
||
|
|
const careerText = await page.$eval('#career-list', el => el.textContent);
|
||
|
|
console.log(` 职业面板: ${careerText.substring(0, 50)}...`);
|
||
|
|
|
||
|
|
// 检查属性面板(6个属性)
|
||
|
|
console.log('6. 检查6属性面板...');
|
||
|
|
const body = await page.$eval('#stat-body', el => el.textContent);
|
||
|
|
const destiny = await page.$eval('#stat-destiny', el => el.textContent);
|
||
|
|
const business = await page.$eval('#stat-business', el => el.textContent);
|
||
|
|
const intelligence = await page.$eval('#stat-intelligence', el => el.textContent);
|
||
|
|
console.log(` 体质: ${body}, 天命: ${destiny}, 经商: ${business}, 智力: ${intelligence}`);
|
||
|
|
|
||
|
|
// 检查商铺面板
|
||
|
|
console.log('7. 检查商铺面板...');
|
||
|
|
const shopExists = await page.$('#shop-panel') !== null;
|
||
|
|
console.log(` 商铺面板存在: ${shopExists}`);
|
||
|
|
|
||
|
|
// 检查神器面板
|
||
|
|
console.log('8. 检查神器面板...');
|
||
|
|
const artifactExists = await page.$('#artifact-list') !== null;
|
||
|
|
console.log(` 神器面板存在: ${artifactExists}`);
|
||
|
|
|
||
|
|
// 点击暂停
|
||
|
|
console.log('9. 测试暂停按钮...');
|
||
|
|
await page.click('#pause-btn');
|
||
|
|
await new Promise(r => setTimeout(r, 500));
|
||
|
|
const dayPaused = await page.$eval('#day', el => el.textContent);
|
||
|
|
await new Promise(r => setTimeout(r, 1000));
|
||
|
|
const dayAfterPause = await page.$eval('#day', el => el.textContent);
|
||
|
|
console.log(` 暂停前天: ${dayPaused}, 暂停后1秒: ${dayAfterPause}`);
|
||
|
|
|
||
|
|
// 点击速度按钮
|
||
|
|
console.log('10. 测试速度切换...');
|
||
|
|
await page.click('[data-speed="1"]');
|
||
|
|
await new Promise(r => setTimeout(r, 1000));
|
||
|
|
console.log(' 速度切换成功');
|
||
|
|
|
||
|
|
console.log('\n=== 浏览器测试全部通过 ===');
|
||
|
|
|
||
|
|
} catch (e) {
|
||
|
|
console.error('\n=== 浏览器测试失败 ===');
|
||
|
|
console.error(e.message);
|
||
|
|
process.exitCode = 1;
|
||
|
|
} finally {
|
||
|
|
await browser.close();
|
||
|
|
server.close();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
runBrowserTest();
|