baseline: 薪酬逻辑收口到 shared/payroll.js 后的当前全量状态
这是第一个包含完整工作区的提交,也是后续「拆 SFC / 上 Vite」的回滚基线。 此前的提交均为 index.html 单文件历史快照,由 .bak 文件重建。 当前状态(提交前已实测): - index.html 内联薪酬算法已删除,改调 WHTPayroll - shared/payroll.js 为唯一薪酬实现,浏览器与 Node 共用 - 对外接口未变:aggregateMonth / isCutEdge / payDayKind 等保留同名薄包装 未入库内容见 .gitignore:依赖、Chrome 验证 profile、验证截图、 运行时 sqlite 数据与日志、时间戳备份、.trash。
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
// 基准对照:把 30 个场景的全部薪酬输出与冻结快照逐字段比。
|
||||
//
|
||||
// 与 payroll.test.js 的分工:
|
||||
// payroll.test.js 写死期望值,说明「为什么该是这个数」——防的是规则本身算错。
|
||||
// 本文件 不判断对错,只判断有没有变——防的是重构悄悄改了数。
|
||||
// 快照由 tools/gen-baseline.js 生成,默认只校验、写要带 --write(历史上它默认写,
|
||||
// 等于 `node --test` 一跑就把网重新描一遍,算错也全绿;那个坑已经堵上了)。
|
||||
//
|
||||
// 红了怎么办:先看差在哪个字段,确认是「有意的业务变更」还是「重构漏了」。
|
||||
// 前者才允许 node tools/gen-baseline.js --write,且要能逐条说清每处差异。
|
||||
// 「测试红了就重新生成基准」= 把安全网剪断。
|
||||
'use strict';
|
||||
|
||||
const test = require('node:test');
|
||||
const assert = require('node:assert/strict');
|
||||
const fs = require('node:fs');
|
||||
const path = require('node:path');
|
||||
const { loadApp } = require('./lib/app-harness.js');
|
||||
const { probeApp, probePure } = require('./lib/probe.js');
|
||||
const { SCENARIOS, NOW } = require('./lib/scenarios.js');
|
||||
|
||||
const BASELINE = path.join(__dirname, 'baseline', 'payroll-baseline.json');
|
||||
|
||||
test('基准文件存在且能解析', () => {
|
||||
assert.ok(fs.existsSync(BASELINE), `缺基准文件 ${BASELINE},先跑 node tools/gen-baseline.js --write`);
|
||||
const raw = JSON.parse(fs.readFileSync(BASELINE, 'utf8'));
|
||||
assert.equal(raw.frozenNow, NOW, '基准的冻结时刻与 scenarios.js 的 NOW 不一致,两边不可比');
|
||||
assert.equal(raw.cases.length, raw.scenarioCount);
|
||||
assert.ok(raw.cases.length > 0);
|
||||
});
|
||||
|
||||
const baseline = JSON.parse(fs.readFileSync(BASELINE, 'utf8'));
|
||||
const byName = new Map(baseline.cases.map((c) => [c.name, c.probe]));
|
||||
|
||||
test('基准场景集与 scenarios.js 完全对应(防止悄悄少测)', () => {
|
||||
const now = SCENARIOS.map((s) => s.name).sort();
|
||||
const old = baseline.cases.map((c) => c.name).sort();
|
||||
assert.deepEqual(now, old, '场景增删后必须显式重写基准:node tools/gen-baseline.js --write');
|
||||
});
|
||||
|
||||
for (const sc of SCENARIOS) {
|
||||
test(`基准 · ${sc.name}`, () => {
|
||||
const want = byName.get(sc.name);
|
||||
assert.ok(want, `基准里没有场景「${sc.name}」`);
|
||||
|
||||
// index.html 现跑值 vs 冻结值
|
||||
const { app } = loadApp({
|
||||
records: sc.records, year: sc.year, month: sc.month,
|
||||
settings: sc.settings, adjust: sc.adjust, now: NOW
|
||||
});
|
||||
assert.deepStrictEqual(probeApp(app), want, 'index.html 的输出与基准不一致');
|
||||
|
||||
// 纯模块现算值 vs 同一份冻结值。
|
||||
// 这一条是为「index.html 拆掉之后」准备的:那天上面那句会失效,
|
||||
// 而只要这句还在,payroll.js 被误改一样会被抓住。
|
||||
assert.deepStrictEqual(probePure(sc, NOW), want, 'shared/payroll.js 的输出与基准不一致');
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user