From 4197fd3b5b005500caa8d3ed0fdcee4c737a48e4 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Tue, 28 Jul 2026 23:45:00 +0000 Subject: [PATCH] test: add missing tests for formatNumber and formatValue Added comprehensive test cases for the string formatting logic located in `src/engine/formatter.ts`. Previously, critical formatting paths lacked coverage, potentially making edge case regressions hard to detect. The new test suite covers standard numbers, formatting settings like custom separators, fallback logic for zero precision (significant figures/conversion noise), dates, percentages, quantity types (hex/binary/octal, fraction, roman), and units. Co-authored-by: Horizontal42 <75383519+Horizontal42@users.noreply.github.com> --- package-lock.json | 4 +- src/engine/formatter.test.ts | 88 ++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+), 2 deletions(-) create mode 100644 src/engine/formatter.test.ts diff --git a/package-lock.json b/package-lock.json index 438d3d1..08a992f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "summarum", - "version": "1.2.1", + "version": "1.2.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "summarum", - "version": "1.2.1", + "version": "1.2.2", "dependencies": { "@codemirror/autocomplete": "^6.18.0", "@codemirror/commands": "^6.8.0", diff --git a/src/engine/formatter.test.ts b/src/engine/formatter.test.ts new file mode 100644 index 0000000..612a120 --- /dev/null +++ b/src/engine/formatter.test.ts @@ -0,0 +1,88 @@ +import { describe, it, expect } from "vitest"; +import { formatNumber, formatValue } from "./formatter"; +import { Decimal, defaultSettings, qty, pct, DateVal, ChartValue, EngineSettings } from "./types"; + +describe("formatNumber", () => { + it("formats standard numbers", () => { + expect(formatNumber(new Decimal("12.345"), defaultSettings)).toBe("12.35"); + expect(formatNumber(new Decimal("100"), defaultSettings)).toBe("100"); + }); + + it("handles custom group separators", () => { + const s: EngineSettings = { ...defaultSettings, groupSeparator: " " }; + expect(formatNumber(new Decimal("1234567.89"), s)).toBe("1 234 567.89"); + }); + + it("handles custom decimal separators", () => { + const s: EngineSettings = { ...defaultSettings, decimalSeparator: "," }; + expect(formatNumber(new Decimal("12.345"), s)).toBe("12,35"); + }); + + it("handles scientific notation strings automatically", () => { + expect(formatNumber(new Decimal("1e25"), defaultSettings)).toBe("1e+25"); + }); + + it("applies significant digits fallback for numbers close to zero", () => { + // 0.001 rounded to 0 decimals is 0, but since >= 1e-12, it shows significant digits + const s: EngineSettings = { ...defaultSettings, precision: 0 }; + expect(formatNumber(new Decimal("0.001"), s)).toBe("0.001"); + }); + + it("treats numbers < 1e-12 as conversion noise", () => { + const s: EngineSettings = { ...defaultSettings, precision: 2 }; + expect(formatNumber(new Decimal("1e-13"), s)).toBe("0"); + }); +}); + +describe("formatValue", () => { + it("formats chart as empty string", () => { + const v: ChartValue = { kind: "chart", points: [], unitLabel: null }; + expect(formatValue(v, defaultSettings)).toBe(""); + }); + + it("formats percent values", () => { + expect(formatValue(pct(25.5), defaultSettings)).toBe("25.5%"); + }); + + it("formats dates depending on flags", () => { + // 2024-01-01 12:00:00 UTC = 1704110400000 + const d: DateVal = { kind: "date", ms: 1704110400000, hasTime: false, timeZone: "UTC" }; + expect(formatValue(d, { ...defaultSettings, dateFormat: "iso" })).toBe("2024-01-01"); + expect(formatValue(d, { ...defaultSettings, dateFormat: "dmy" })).toBe("01.01.2024"); + expect(formatValue(d, { ...defaultSettings, dateFormat: "mdy" })).toBe("01/01/2024"); + + // Test timeOnly + const dTime: DateVal = { kind: "date", ms: 1704110400000, hasTime: true, timeZone: "UTC", timeOnly: true }; + expect(formatValue(dTime, defaultSettings)).toBe("12:00"); + }); + + it("formats base conversions", () => { + expect(formatValue(qty(255, null, "hex"), defaultSettings)).toBe("0xFF"); + expect(formatValue(qty(-255, null, "hex"), defaultSettings)).toBe("-0xFF"); + expect(formatValue(qty(5, null, "binary"), defaultSettings)).toBe("0b101"); + expect(formatValue(qty(8, null, "octal"), defaultSettings)).toBe("0o10"); + }); + + it("formats representations", () => { + expect(formatValue(qty(123456, null, "scientific"), defaultSettings)).toBe("1.23e5"); + expect(formatValue(qty(1234.56, null, "plain"), defaultSettings)).toBe("1234.56"); + expect(formatValue(qty(0.75, null, "fraction"), defaultSettings)).toBe("3/4"); + expect(formatValue(qty(14, null, "roman"), defaultSettings)).toBe("XIV"); + }); + + it("formats Roman numerals fallbacks", () => { + // Beyond 3999 falls back to formatNumber + expect(formatValue(qty(4000, null, "roman"), defaultSettings)).toBe("4,000"); + }); + + it("formats units", () => { + const cm = { id: "cm", dimension: "length" as const, ratio: new Decimal(0.01), format: "cm" }; + expect(formatValue(qty(10, cm), defaultSettings)).toBe("10 cm"); + + const degC = { id: "degC", dimension: "temperature" as const, ratio: new Decimal(1), format: "°C" }; + expect(formatValue(qty(25, degC), defaultSettings)).toBe("25°C"); + + const usd = { id: "USD", dimension: "currency" as const, ratio: new Decimal(1), format: "${}" }; + expect(formatValue(qty(100, usd), defaultSettings)).toBe("$100"); + }); +});