首次提交: OnebotCatalog 项目代码与文档(含 NX 按需生成服务二期、后台、一键启动)
This commit is contained in:
90
tools/e2e-gen.js
Normal file
90
tools/e2e-gen.js
Normal file
@@ -0,0 +1,90 @@
|
||||
// 无头 E2E: 非标档位在线生成 (二期) — 按钮升级/立即命中下载/排队轮询下载
|
||||
// 前置: 站点 config.js 的 api 已指向本地 GenServer (匿名模式); GenServer 已启动
|
||||
// 用法: node e2e-gen.js <siteUrl> <jobsDir> <outputDir>
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
let chromium;
|
||||
try { chromium = require('playwright-core').chromium; }
|
||||
catch (e) { chromium = require('C:/Users/ruigu/AppData/Local/Temp/nds3dtest/node_modules/playwright-core').chromium; }
|
||||
const edge = 'C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe';
|
||||
|
||||
(async () => {
|
||||
const url = process.argv[2] || 'http://localhost:8080/';
|
||||
const jobsDir = process.argv[3];
|
||||
const outputDir = process.argv[4];
|
||||
const browser = await chromium.launch({ executablePath: edge, headless: true });
|
||||
const context = await browser.newContext({ acceptDownloads: true, viewport: { width: 1600, height: 900 } });
|
||||
const page = await context.newPage();
|
||||
const errs = [];
|
||||
page.on('pageerror', e => errs.push(e.message));
|
||||
await page.goto(url, { waitUntil: 'domcontentloaded' });
|
||||
await page.waitForTimeout(2500);
|
||||
|
||||
let pass = 0, fail = 0;
|
||||
const out = [];
|
||||
const check = (name, ok) => { out.push((ok ? 'PASS ' : 'FAIL ') + name); if (ok) pass++; else fail++; };
|
||||
|
||||
// KC 系列
|
||||
const names = await page.$$eval('.tree .series', els => els.map(e => e.textContent.trim()));
|
||||
await (await page.$$('.tree .series'))[names.findIndex(n => n.indexOf('KC') === 0)].click();
|
||||
await page.waitForTimeout(500);
|
||||
|
||||
const setSel = async (code, val) => { await page.selectOption('#sel-' + code, val); await page.waitForTimeout(250); };
|
||||
const setStroke = async (v) => { await page.fill('#sel-stroke', String(v)); await page.dispatchEvent('#sel-stroke', 'change'); await page.waitForTimeout(400); };
|
||||
const btn = async () => page.$eval('#btnDownload', el => ({ text: el.textContent, disabled: el.disabled, hidden: el.classList.contains('hidden') }));
|
||||
|
||||
// 1) 非标 87 (输出目录已预置) → 按钮=在线生成数模; 点击 → immediate → 触发下载
|
||||
await setSel('type', '00'); await setSel('bore', '32'); await setStroke(87);
|
||||
await setSel('magnet', '__EMPTY__'); await setSel('mount', '__EMPTY__'); await page.waitForTimeout(400);
|
||||
var b = await btn();
|
||||
check('非标按钮 = 在线生成数模 且可用 (实际: ' + b.text + (b.disabled ? '/disabled' : '/enabled') + ')',
|
||||
b.text.indexOf('在线生成') >= 0 && !b.disabled);
|
||||
var dlEvent = null;
|
||||
page.waitForEvent('download', { timeout: 10000 }).then(d => { dlEvent = d; }).catch(() => { });
|
||||
await page.click('#btnDownload');
|
||||
await page.waitForTimeout(2500);
|
||||
check('立即命中 → 触发全格式 zip 下载', dlEvent !== null);
|
||||
var st = await page.$eval('#status', el => el.textContent);
|
||||
check('状态含 就绪/下载 (实际: ' + st.trim() + ')', st.indexOf('就绪') >= 0 || st.indexOf('下载') >= 0);
|
||||
|
||||
// 2) 非标 88 (无输出) → 点击 → 排队/生成中 → 外部模拟 worker 完成 → 触发下载
|
||||
await setStroke(88); await page.waitForTimeout(400);
|
||||
b = await btn();
|
||||
check('非标 88 按钮可用', b.text.indexOf('在线生成') >= 0 && !b.disabled);
|
||||
dlEvent = null;
|
||||
page.waitForEvent('download', { timeout: 30000 }).then(d => { dlEvent = d; }).catch(() => { });
|
||||
await page.click('#btnDownload');
|
||||
await page.waitForTimeout(4000);
|
||||
b = await btn();
|
||||
check('点击后进入生成/排队态 (实际: ' + b.text + ')', b.text.indexOf('生成') >= 0 || b.text.indexOf('队列') >= 0);
|
||||
// 模拟 worker: 认领 .json → .running → 造输出 → 写 .done
|
||||
const jobs = fs.readdirSync(jobsDir).filter(f => f.startsWith('job_') && f.endsWith('.json'));
|
||||
if (jobs.length) {
|
||||
const jf = path.join(jobsDir, jobs[0]);
|
||||
const rf = jf.replace(/\.json$/, '.running');
|
||||
fs.renameSync(jf, rf);
|
||||
const o = path.join(outputDir, 'KC', 'KC0032-88');
|
||||
fs.mkdirSync(o, { recursive: true });
|
||||
['KC0032-88.stp', 'KC0032-88.x_t', 'KC0032-88.igs', 'KC0032-88.stl'].forEach(f => fs.writeFileSync(path.join(o, f), 'FAKE ' + f));
|
||||
fs.writeFileSync(jf.replace(/\.json$/, '.done'), JSON.stringify({
|
||||
ok: true, error: '',
|
||||
items: [{ series: 'KC', code: 'KC0032-88', ok: true, hit: false, files: ['KC0032-88.stp', 'KC0032-88.x_t', 'KC0032-88.igs', 'KC0032-88.stl'] }]
|
||||
}));
|
||||
fs.unlinkSync(rf);
|
||||
check('模拟 worker 完成写入', true);
|
||||
} else {
|
||||
check('任务已入队 (jobs 目录可见)', jobs.length > 0);
|
||||
}
|
||||
await page.waitForTimeout(12000); // 轮询间隔 3s, 等状态刷新并触发下载
|
||||
check('排队轮询 → 完成后触发下载', dlEvent !== null);
|
||||
|
||||
// 3) 标准档位回归: stroke=10 → 按钮回 下载 STEP 可用
|
||||
await setStroke(10); await page.waitForTimeout(400);
|
||||
b = await btn();
|
||||
check('标准档位按钮回 下载 STEP (实际: ' + b.text + ')', b.text.indexOf('下载 STEP') >= 0 && !b.disabled && !b.hidden);
|
||||
|
||||
console.log(out.join('\n'));
|
||||
console.log('结果: ' + pass + ' 通过, ' + fail + ' 失败 | 页面错误: ' + (errs.length ? errs.join(' | ') : '无'));
|
||||
await browser.close();
|
||||
process.exit(fail ? 1 : 0);
|
||||
})().catch(e => { console.error('FAIL:', e.message); process.exit(1); });
|
||||
Reference in New Issue
Block a user