import { describe, expect, it } from "vitest"; import { convertDocument } from "../../src/core/convert"; import { DATA_LIMITS } from "../../src/core/limits"; import { parseDataDocument } from "../../src/core/parse"; import { flattenRows, queryPointer, querySafePath, tableFromNode, } from "../../src/core/query"; const document = parseDataDocument({ source: '{"a/b":{"~key":7},"people":[{"name":"Ada","role":"math"},{"name":"Grace","role":"code"}]}', format: "json", }); describe("safe data projections", () => { it("resolves RFC 6901 escaping", () => { expect(queryPointer(document.root, "/a~1b/~0key")[0]?.node).toMatchObject({ type: "number", raw: "7", }); }); it("supports a deliberately small non-evaluating path syntax", () => { expect(querySafePath(document.root, "$.people[*].name")).toHaveLength(2); expect( querySafePath(document.root, "$['a/b']['~key']")[0]?.node, ).toMatchObject({ raw: "7" }); expect(() => querySafePath(document.root, "$..name")).toThrow( /unsupported path syntax/iu, ); expect(() => querySafePath(document.root, "$.people[?(@.role)]")).toThrow( /filters/iu, ); expect(() => queryPointer( document.root, `/${"a".repeat(DATA_LIMITS.maxQueryCharacters)}`, ), ).toThrow(/Query character count/iu); }); it("projects record arrays and flattened scalar leaves", () => { const people = queryPointer(document.root, "/people")[0]?.node; expect(people && tableFromNode(people)).toMatchObject({ columns: ["name", "role"], rows: [ ["Ada", "math"], ["Grace", "code"], ], }); expect(flattenRows(document.root).rows).toEqual( expect.arrayContaining([["/a~1b/~0key", "number", "7"]]), ); }); }); describe("explicit conversions", () => { it("neutralises spreadsheet formula cells only when requested", () => { const csv = parseDataDocument({ source: 'name,value\ncalc,"=2+2"\nsafe,text', format: "csv", }); const protectedOutput = convertDocument(csv, "csv", { spreadsheetSafe: true, }); expect(protectedOutput.text).toContain("'=2+2"); expect(protectedOutput.events).toEqual( expect.arrayContaining([ expect.objectContaining({ code: "csv.formula-neutralized" }), ]), ); const raw = convertDocument(csv, "csv", { spreadsheetSafe: false }); expect(raw.text).toContain("=2+2"); expect(raw.events).toEqual( expect.arrayContaining([ expect.objectContaining({ code: "csv.formula-unchecked" }), ]), ); }); it("turns unsafe decimals into strings rather than silently rounding", () => { const precise = parseDataDocument({ source: '{"value":0.1234567890123456789012345}', format: "json", }); const yaml = convertDocument(precise, "yaml"); expect(yaml.events).toEqual( expect.arrayContaining([ expect.objectContaining({ code: "yaml.unsafe-number" }), ]), ); expect(yaml.text).toContain("0.1234567890123456789012345"); }); it("reports null and root coercion when targeting TOML", () => { const value = parseDataDocument({ source: "null", format: "json" }); const result = convertDocument(value, "toml"); expect(result.text).toContain('value = ""'); expect(result.events.map((event) => event.code)).toEqual( expect.arrayContaining(["toml.null", "toml.root-table"]), ); }); it("converts ordinary data to XML using a disclosed stable convention", () => { const result = convertDocument(document, "xml"); expect(result.text).toContain(""); expect(result.text).toContain("Ada"); expect(result.events).toEqual( expect.arrayContaining([ expect.objectContaining({ code: "xml.mapping" }), ]), ); }); });