spb/earth-now Public License
earth-now.co — real-time planetary dashboard: live world metrics modeled, not streamed.
TypeScript 93%
Shell 2.3%
SQL 1.4%
JavaScript 1.3%
Dockerfile 1.2%
CSS 0.8%
1/**2 * earth-now.co3 * Author: Simon-Pierre Boucher4 * Contact: contact@spboucher.ai5 * File: packages/counter/test/consistency.test.ts6 * Purpose: Client/server consistency — jsdom (browser-like) and a spawned Node process must produce bit-identical values7 *8 * @vitest-environment jsdom9 */1011import { execFileSync } from "node:child_process";12import { fileURLToPath } from "node:url";13import { dirname, join } from "node:path";14import { describe, expect, it } from "vitest";15import { type CounterModel, counterValue } from "../src/index";1617const MODELS: CounterModel[] = [18 {19 metricId: "consistency_linear",20 anchorValue: 12345.678,21 anchorTime: "2026-01-01T00:00:00.000Z",22 rateFn: { kind: "linear", perSecond: 1.2345 },23 observedAt: "2026-01-01T00:00:00.000Z",24 sourceId: "test",25 modelVersion: "test-v1",26 displayHints: { decimals: 0, unit: "u" },27 },28 {29 metricId: "consistency_seasonal",30 anchorValue: 1e9,31 anchorTime: "2026-01-01T00:00:00.000Z",32 rateFn: {33 kind: "seasonal",34 base: 4.17,35 harmonics: [36 { period: "year", order: 1, amplitude: 0.146, phase: 1.8449 },37 { period: "day", order: 1, amplitude: 0.02, phase: 2.88 },38 ],39 },40 observedAt: "2025-07-01T00:00:00.000Z",41 sourceId: "test",42 modelVersion: "test-v1",43 displayHints: { decimals: 0, unit: "u" },44 },45 {46 metricId: "consistency_spline",47 anchorValue: 8231000000,48 anchorTime: "2025-07-01T00:00:00.000Z",49 rateFn: {50 kind: "spline",51 knots: [52 ["2023-07-01T00:00:00.000Z", 8091000000],53 ["2024-07-01T00:00:00.000Z", 8161000000],54 ["2025-07-01T00:00:00.000Z", 8231000000],55 ["2026-07-01T00:00:00.000Z", 8299000000],56 ],57 },58 observedAt: "2025-07-01T00:00:00.000Z",59 sourceId: "test",60 modelVersion: "test-v1",61 displayHints: { decimals: 0, unit: "u" },62 },63];6465const INSTANTS = [66 "2026-01-01T00:00:00.000Z",67 "2026-03-14T15:09:26.535Z",68 "2026-08-09T12:00:00.000Z",69 "2026-12-31T23:59:59.999Z",70 "2027-06-15T06:30:00.000Z",71].map((iso) => Date.parse(iso));7273describe("client/server consistency (bit-identical values)", () => {74 it("runs under jsdom", () => {75 expect(typeof document).toBe("object");76 });7778 it("jsdom and a separate Node process agree exactly on every model × instant", () => {79 const here = counterValue !== undefined;80 expect(here).toBe(true);8182 const inJsdom = MODELS.map((m) => INSTANTS.map((t) => counterValue(m, t)));8384 // Evaluate the SAME models in a plain Node child process against the built dist.85 const distIndex = join(dirname(fileURLToPath(import.meta.url)), "..", "dist", "index.js");86 const script = `87 const { counterValue } = await import(${JSON.stringify(distIndex)});88 const models = ${JSON.stringify(MODELS)};89 const instants = ${JSON.stringify(INSTANTS)};90 const out = models.map((m) => instants.map((t) => counterValue(m, t)));91 console.log(JSON.stringify(out));92 `;93 const stdout = execFileSync(process.execPath, ["--input-type=module", "-e", script], {94 encoding: "utf8",95 });96 const inNode = JSON.parse(stdout) as number[][];9798 // JSON round-trips finite doubles exactly (shortest round-trip repr), so99 // toEqual here really is bit-identity.100 expect(inNode).toEqual(inJsdom);101 for (let i = 0; i < MODELS.length; i++) {102 for (let j = 0; j < INSTANTS.length; j++) {103 expect(Object.is(inNode[i]![j]!, inJsdom[i]![j]!)).toBe(true);104 }105 }106 });107});108