fix(plugins): unique csv row keys, per-file default mediaType, scale-aware zero rating

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
This commit is contained in:
Lucas Winther
2026-10-30 15:51:22 +01:00
co-authored by Claude Sonnet 5.5
parent a540c7d34d
commit 4c08c16e48
3 changed files with 50 additions and 12 deletions
+30
View File
@@ -66,4 +66,34 @@ describe("csv plugin", () => {
test("unsupported extension throws", async () => {
await expect(run("x.txt", new Uint8Array())).rejects.toThrow();
});
const enc = (s: string) => new TextEncoder().encode(s);
test("duplicate rows get distinct deterministic keys", async () => {
const csv = "Title,Date Read\nA,2020-01-01\nA,2020-01-01\nB,\nB,\nB,\n";
const keys = async () => (await run("d.csv", enc(csv))).map((r) => r.key);
const k = await keys();
expect(new Set(k).size).toBe(k.length);
expect(k[0]).toMatch(/^row:[0-9a-f]{40}$/);
expect(k.some((x) => x.endsWith("#2"))).toBe(true);
expect(k.some((x) => x.endsWith("#3"))).toBe(true);
expect(await keys()).toEqual(k);
});
test("default mediaType is per file, not per row", async () => {
const csv = "Title,Author,ISBN13\nA,Someone,=\"9780441172719\"\nB,,\n";
const e = entries(await run("g.csv", enc(csv)));
expect(e.map((r) => r.work.mediaType)).toEqual(["book", "book"]);
const plain = entries(await run("p.csv", enc("Title\nA\n")));
expect(plain[0]!.work.mediaType).toBe("other");
const j = entries(await run("j.json", enc('[{"title":"A","author":"x"},{"title":"B"},{"title":"C","mediaType":"game"}]')));
expect(j.map((r) => r.work.mediaType)).toEqual(["book", "book", "game"]);
});
test("rating 0 is unrated only on scale 5", async () => {
const m = JSON.stringify({ T: "title", R: "rating" });
const rate = async (csv: string) => entries(await run("r.csv", enc(csv), { mapping: m })).map((r) => r.entry.rating ?? null);
expect(await rate("T,R\nA,0\nB,4\n")).toEqual([null, 80]);
expect(await rate("T,R\nA,0\nB,8\n")).toEqual([0, 80]);
expect(await rate("T,R\nA,0\nB,80\n")).toEqual([0, 80]);
});
});