test(build): catch behavioral drift in bundle summary via eval-extracted comparison
This commit is contained in:
@@ -25,3 +25,49 @@ test('userscript self-test block is wired to #tat-test', () => {
|
|||||||
assert.ok(bundle.includes("location.hash === '#tat-test'"), 'self-test guard missing');
|
assert.ok(bundle.includes("location.hash === '#tat-test'"), 'self-test guard missing');
|
||||||
assert.ok(bundle.includes('runSelfTest'), 'runSelfTest function missing');
|
assert.ok(bundle.includes('runSelfTest'), 'runSelfTest function missing');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('bundle summary behavior matches src/pure.js (catches Math.floor-style regressions)', () => {
|
||||||
|
// Read both the source and the bundle.
|
||||||
|
const src = readFileSync(join(root, 'src/pure.js'), 'utf8');
|
||||||
|
const bundle = readFileSync(join(root, 'torn-attribute-tracker.user.js'), 'utf8');
|
||||||
|
|
||||||
|
// Extract the body of `summary` from src/pure.js between `function summary(` and the next `}`.
|
||||||
|
// Use a simple state machine: find the function header, then count braces.
|
||||||
|
function extractBody(source, fnName) {
|
||||||
|
const start = source.indexOf('function ' + fnName + '(');
|
||||||
|
if (start === -1) throw new Error('could not find ' + fnName + ' in source');
|
||||||
|
// Find the opening brace of the function body.
|
||||||
|
let i = source.indexOf('{', start);
|
||||||
|
if (i === -1) throw new Error('no opening brace for ' + fnName);
|
||||||
|
let depth = 1;
|
||||||
|
i++;
|
||||||
|
while (i < source.length && depth > 0) {
|
||||||
|
const c = source[i];
|
||||||
|
if (c === '{') depth++;
|
||||||
|
else if (c === '}') depth--;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return source.slice(start, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Eval-extract the `summary` function from both sources. The src/pure.js
|
||||||
|
// version references the module-level `MS_PER_DAY` constant, so inject
|
||||||
|
// it into the eval scope; the bundle inlines the literal value, so the
|
||||||
|
// injected binding is a harmless no-op there.
|
||||||
|
const srcSummary = eval('(function() { const MS_PER_DAY = 86_400_000; ' + extractBody(src, 'summary') + ' ; return summary; })()');
|
||||||
|
const bundleSummary = eval('(function() { const MS_PER_DAY = 86_400_000; ' + extractBody(bundle, 'summary') + ' ; return summary; })()');
|
||||||
|
|
||||||
|
// Run both with a known input that exercises perDay flooring.
|
||||||
|
const NOW = 1_700_000_000_000;
|
||||||
|
const entries = [
|
||||||
|
{ ts: NOW - 1000, delta: 247 },
|
||||||
|
{ ts: NOW - 2000, delta: 247 },
|
||||||
|
];
|
||||||
|
const srcResult = srcSummary(entries, NOW);
|
||||||
|
const bundleResult = bundleSummary(entries, NOW);
|
||||||
|
|
||||||
|
// The bundle MUST match the source exactly.
|
||||||
|
assert.deepEqual(bundleResult, srcResult, 'bundle summary differs from src/pure.js summary');
|
||||||
|
// And specifically: perDay must be the floored integer 70, not the float 70.57.
|
||||||
|
assert.equal(bundleResult.perDay, 70, 'perDay should be floored to 70');
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user