Files
work-hours-tracker/png/retry_test.js
T
OpenClaw Agent 2329955e32 baseline: 薪酬逻辑收口到 shared/payroll.js 后的当前全量状态
这是第一个包含完整工作区的提交,也是后续「拆 SFC / 上 Vite」的回滚基线。

此前的提交均为 index.html 单文件历史快照,由 .bak 文件重建。

当前状态(提交前已实测):
- index.html 内联薪酬算法已删除,改调 WHTPayroll
- shared/payroll.js 为唯一薪酬实现,浏览器与 Node 共用
- 对外接口未变:aggregateMonth / isCutEdge / payDayKind 等保留同名薄包装

未入库内容见 .gitignore:依赖、Chrome 验证 profile、验证截图、
运行时 sqlite 数据与日志、时间戳备份、.trash。
2026-09-05 14:35:00 +08:00

79 lines
3.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 实测自动重试:用请求拦截模拟「Vue 前 N 次取不到」,看页面能否自己恢复。
//
// 场景对应真实故障:服务端日志里失败的请求压根没有记录,说明请求没到服务器(链路丢包)。
// 这里用 request.abort() 复现同一效果 —— 浏览器侧看到的就是「拿不到这个文件」。
const puppeteer = require('/root/.openclaw/workspace/web_tasks/node_modules/puppeteer');
const fs = require('fs');
const URL = 'http://127.0.0.1:9522/';
const VUE = 'vue.global.prod.js';
async function run(label, failTimes, expect) {
const profile = `/tmp/wht-retry-${failTimes}`;
fs.rmSync(profile, { recursive: true, force: true });
const browser = await puppeteer.launch({
executablePath: '/usr/bin/chromium',
headless: 'new',
userDataDir: profile,
args: ['--no-sandbox', '--disable-gpu', '--disable-dev-shm-usage']
});
const page = await browser.newPage();
await page.setViewport({ width: 390, height: 844, isMobile: true, deviceScaleFactor: 2 });
let blocked = 0, served = 0;
await page.setRequestInterception(true);
page.on('request', r => {
if (r.url().includes(VUE)) {
if (blocked < failTimes) { blocked++; return r.abort('failed'); }
served++;
}
r.continue();
});
await page.goto(URL, { waitUntil: 'domcontentloaded', timeout: 30000 });
// 自动重试有 800ms 递增退避 + reload,留足时间
await new Promise(r => setTimeout(r, 6000));
const s = await page.evaluate(() => {
const card = document.getElementById('boot-fail');
return {
vue: typeof Vue !== 'undefined',
cardShown: card ? !card.hidden : false,
title: document.getElementById('boot-title')?.textContent || null,
detail: document.getElementById('boot-detail')?.textContent || null,
btnHidden: document.getElementById('boot-retry')?.hidden ?? null,
mounted: !!document.querySelector('#app')?.innerText?.trim().length,
retryCount: sessionStorage.getItem('wht_boot_retry')
};
});
const pass = expect(s);
console.log(`\n[${pass ? 'PASS' : 'FAIL'}] ${label}`);
console.log(` 拦截 ${blocked} 次 / 放行 ${served} 次`);
console.log(` Vue=${s.vue} 已挂载=${s.mounted} 卡片显示=${s.cardShown} 重试计数=${s.retryCount}`);
if (s.cardShown) console.log(` 标题="${s.title}"\n 详情="${s.detail}"`);
await page.screenshot({
path: `/root/.openclaw/workspace/work-hours-tracker/png/retry_fail${failTimes}.png`
});
await browser.close();
fs.rmSync(profile, { recursive: true, force: true });
return pass;
}
(async () => {
const results = [];
// 0 次失败:正常路径,卡片不该出现
results.push(await run('正常加载(不拦截)', 0, s => s.vue && s.mounted && !s.cardShown));
// 1 次失败:应自动重试成功,用户看不到失败卡
results.push(await run('丢包 1 次 → 自动恢复', 1, s => s.vue && s.mounted && !s.cardShown));
// 999 次失败:自动重试全败,应显示卡片且按钮可点
results.push(await run('持续丢包 → 显示卡片且不刷新循环', 999,
s => !s.vue && s.cardShown && s.title === '页面没能加载完成' && s.btnHidden === false));
console.log('\n' + '='.repeat(46));
console.log(results.every(Boolean) ? `全部通过(${results.length}/${results.length})` : '有失败项');
console.log('='.repeat(46));
process.exit(results.every(Boolean) ? 0 : 1);
})().catch(e => { console.error('FAIL', e); process.exit(1); });