import { describe, expect, it } from "vitest";
import { csvDocument, csvRate } from "@/lib/csv";
/**
* `csvRate()`(D-164。ユーザー指示 2026-10-06「値がないとこは空欄で」)。
* null は空欄。値があれば四捨五入の整数+`%`(丸めは表示のみ。CLAUDE.md §4.3)。
*/
describe("csvRate — 率のセル", () => {
const cases: Array<[string, number | null, string]> = [
["null → 空欄('- にしない)", null, ""],
["89.5 → 90%(四捨五入)", 89.5, "90%"],
["91.4 → 91%", 91.4, "91%"],
["0 → 0%(0 は値がある。空欄にしない)", 0, "0%"],
];
it.each(cases)("%s", (_name, input, expected) => {
expect(csvRate(input)).toBe(expected);
});
});
/**
* `csvDocument()`(D-163)。清掃詳細ログとレポートの施設別パフォーマンスが共有する。
* `csvCell()` 単体の期待値表は `lib/clean-logs/__tests__/csv.test.ts`(再エクスポート経由で同じ関数)。
*/
describe("csvDocument — 文書の形", () => {
it("先頭が BOM・行区切りは CRLF・最後の行も CRLF で終わる", () => {
const out = csvDocument(["a", "b"], [["1", "2"], ["3", "4"]]);
expect(out).toBe("a,b\r\n1,2\r\n3,4\r\n");
});
it("0件ならBOM + ヘッダ + CRLF だけ", () => {
expect(csvDocument(["a", "b"], [])).toBe("a,b\r\n");
});
it("★ヘッダはエスケープしない★(清掃詳細ログの元の出力と揃える)", () => {
expect(csvDocument(["=x"], [])).toBe("=x\r\n");
});
it("★データ行は全セルを csvCell() に通す★(数式対策と RFC 4180 の引用)", () => {
const out = csvDocument(["a", "b", "c"], [["-", '=HYPERLINK("x")', "中央店, 本館"]]);
expect(out).toBe('a,b,c\r\n\'-,"\'=HYPERLINK(""x"")","中央店, 本館"\r\n');
});
it("空文字のセルは空のまま並ぶ", () => {
expect(csvDocument(["a", "b"], [["", ""]])).toBe("a,b\r\n,\r\n");
});
});