// Headless guard for the trace-chart viewer's x-mode + interaction wiring. // Properties: (1) the DEFAULT x spine is ORDINAL — data[0] is [0..n-1], not the raw // timestamps, so non-trading gaps collapse; the x-axis carries an index->label values // formatter. (2) "continuous" mode restores data[0] === xs verbatim. (3) panels carry a // shared cursor.sync.key so the crosshair lines up. (4) every config attaches an // interaction plugin with an init hook. Drives the pure buildCharts; no DOM/uPlot. import { createRequire } from "node:module"; import { readFileSync } from "node:fs"; import { fileURLToPath } from "node:url"; import { dirname, join } from "node:path"; const require = createRequire(import.meta.url); const here = dirname(fileURLToPath(import.meta.url)); const traces = JSON.parse(readFileSync(join(here, "fixtures", "sample-traces.json"), "utf8")); const fail = (msg) => { console.error("FAIL: " + msg); process.exit(1); }; const sameArr = (a, b, msg) => { if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length || a.some((v, i) => v !== b[i])) fail(msg); }; global.window = { AURA_TRACES: traces }; const { buildCharts } = require(join(here, "..", "assets", "chart-viewer.js")); const n = traces.xs.length; const idx = Array.from({ length: n }, (_, i) => i); // (1) default is ordinal: data[0] is the index spine, with an x-axis values formatter. const ov = buildCharts(traces, "overlay"); sameArr(ov[0].data[0], idx, "default overlay x is the ordinal index spine [0..n-1]"); if (typeof ov[0].opts.axes[0].values !== "function") fail("ordinal overlay x-axis lacks a values formatter"); // (4) interaction wired: a plugin with an init hook. if (!Array.isArray(ov[0].opts.plugins) || ov[0].opts.plugins.length < 1) fail("no interaction plugin attached"); if (typeof ov[0].opts.plugins[0].hooks.init !== "function") fail("interaction plugin has no init hook"); // (2) continuous mode: data[0] is xs verbatim. const ovc = buildCharts(traces, "overlay", "continuous"); sameArr(ovc[0].data[0], traces.xs, "continuous overlay x is xs verbatim"); // (3) panels: cursor.sync.key present and equal across panels; default still ordinal. const panels = buildCharts(traces, "panels"); const keys = panels.map((p) => p.opts.cursor && p.opts.cursor.sync && p.opts.cursor.sync.key); if (keys.some((k) => !k)) fail("a panel lacks cursor.sync.key"); if (new Set(keys).size !== 1) fail("panels do not share one cursor.sync key"); sameArr(panels[0].data[0], idx, "default panel x is the ordinal index spine"); console.log("OK — ordinal default + continuous toggle + panel cursor-sync + interaction plugin."); process.exit(0);