diff --git a/tests/build.test.js b/tests/build.test.js index 4c5b53b..370ab99 100644 --- a/tests/build.test.js +++ b/tests/build.test.js @@ -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('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'); +});