Unify reader cleanup rules, lock writer table guards, and register the exact fictional timestamp collision. Preserve existing ordinary-report safety contracts and source-data gaps. Validation: report Node 165/165, final safety 29/29, Python 101/101, Chrome 28/28; both PDFs retain all 130 rows. Full Node 3704 tests with the same 91 baseline failures. Privacy test: 62 passed, 1 failed due to 17 protected-file READ_ERRORs; not a green gate. Build, DB, manual checklist and controlled-login gaps remain documented. User explicitly authorized staging push with these gaps disclosed. Co-Authored-By: Claude Code <noreply@anthropic.com>
56 lines
2.7 KiB
TypeScript
56 lines
2.7 KiB
TypeScript
import assert from "node:assert/strict";
|
|
import { readFileSync } from "node:fs";
|
|
import test from "node:test";
|
|
import { bindFactTablePrint } from "../src/lib/report-fact-table-print";
|
|
|
|
function setup() {
|
|
const details = [{ open: false }, { open: true }, { open: false }];
|
|
const outside = { open: false };
|
|
const events = new EventTarget();
|
|
const root = { querySelectorAll(selector: string) { assert.equal(selector, "details"); return details; } };
|
|
const cleanup = bindFactTablePrint(root as unknown as HTMLElement, events);
|
|
return { details, outside, events, cleanup };
|
|
}
|
|
|
|
test("fact table printing expands all report groups and restores mixed disclosure state", () => {
|
|
const { details, outside, events, cleanup } = setup();
|
|
assert.deepEqual(details.map(item => item.open), [false, true, false]);
|
|
events.dispatchEvent(new Event("beforeprint"));
|
|
assert.deepEqual(details.map(item => item.open), [true, true, true]);
|
|
assert.equal(outside.open, false);
|
|
events.dispatchEvent(new Event("afterprint"));
|
|
assert.deepEqual(details.map(item => item.open), [false, true, false]);
|
|
cleanup();
|
|
});
|
|
|
|
test("fact table printing preserves the first snapshot across repeated beforeprint events", () => {
|
|
const { details, events, cleanup } = setup();
|
|
events.dispatchEvent(new Event("beforeprint"));
|
|
events.dispatchEvent(new Event("beforeprint"));
|
|
events.dispatchEvent(new Event("afterprint"));
|
|
assert.deepEqual(details.map(item => item.open), [false, true, false]);
|
|
details[0].open = true;
|
|
events.dispatchEvent(new Event("beforeprint"));
|
|
events.dispatchEvent(new Event("afterprint"));
|
|
assert.deepEqual(details.map(item => item.open), [true, true, false]);
|
|
cleanup();
|
|
});
|
|
|
|
test("fact table print cleanup restores pending state and removes both event listeners", () => {
|
|
const { details, events, cleanup } = setup();
|
|
events.dispatchEvent(new Event("afterprint"));
|
|
events.dispatchEvent(new Event("beforeprint"));
|
|
cleanup();
|
|
assert.deepEqual(details.map(item => item.open), [false, true, false]);
|
|
events.dispatchEvent(new Event("beforeprint"));
|
|
assert.deepEqual(details.map(item => item.open), [false, true, false]);
|
|
});
|
|
|
|
test("fact table print styles remove horizontal clipping and repeat table headers", () => {
|
|
const css = readFileSync(new URL("../src/app/globals.css", import.meta.url), "utf8");
|
|
const print = css.slice(css.indexOf("@media print"), css.indexOf("@theme inline"));
|
|
assert.match(print, /\.personal-report-fact-table-scroll\s*\{[^}]*overflow: visible !important/);
|
|
assert.match(print, /\.personal-report-fact-tables table\s*\{[^}]*table-layout: fixed/);
|
|
assert.match(print, /\.personal-report-fact-tables thead\s*\{[^}]*display: table-header-group/);
|
|
});
|