// Unit tests for the dependency-free RFC-4180 CSV serializer (csv.ts).
// Pure — touches no mocked module, so it is immune to the process-global
// mock.module registry shared with the sibling audit.test.ts.
import { describe, expect, test } from "bun:test";
import { toCsv } from "./csv";

describe("toCsv", () => {
  test("emits a header row then one line per row, CRLF-separated", () => {
    const out = toCsv(
      ["a", "b"],
      [
        { a: "1", b: "2" },
        { a: "3", b: "4" },
      ],
    );
    expect(out).toBe("a,b\r\n1,2\r\n3,4");
  });

  test("null/undefined/missing become empty fields", () => {
    const out = toCsv(
      ["a", "b", "c"],
      [{ a: null, b: undefined }], // c is absent entirely
    );
    expect(out).toBe("a,b,c\r\n,,");
  });

  test("quotes fields containing commas, quotes or newlines and doubles inner quotes", () => {
    const out = toCsv(
      ["v"],
      [
        { v: "has,comma" },
        { v: 'has"quote' },
        { v: "has\nnewline" },
        { v: "has\r\ncrlf" },
        { v: "plain" },
      ],
    );
    expect(out).toBe(
      [
        "v",
        '"has,comma"',
        '"has""quote"',
        '"has\nnewline"',
        '"has\r\ncrlf"',
        "plain",
      ].join("\r\n"),
    );
  });

  test("stringifies primitives, Dates (ISO) and objects (JSON)", () => {
    const d = new Date("2026-01-02T03:04:05.000Z");
    const out = toCsv(
      ["num", "bool", "date", "obj"],
      [{ num: 42, bool: false, date: d, obj: { k: "v" } }],
    );
    // The object JSON contains a comma+quotes so it is wrapped/escaped.
    expect(out).toBe(
      `num,bool,date,obj\r\n42,false,2026-01-02T03:04:05.000Z,"{""k"":""v""}"`,
    );
  });
});
