113 lines
3.3 KiB
TypeScript
113 lines
3.3 KiB
TypeScript
import { describe, it, expect } from "vitest";
|
|
import { parseCsv } from "../loader";
|
|
|
|
describe("parseCsv - basic parsing", () => {
|
|
it("should parse a simple CSV with primitive types", () => {
|
|
const csv = [
|
|
"name,age,active",
|
|
"string,number,boolean",
|
|
"Alice,30,true",
|
|
"Bob,25,false",
|
|
].join("\n");
|
|
|
|
const result = parseCsv(csv, { emitTypes: false });
|
|
|
|
expect(result.data).toHaveLength(2);
|
|
expect(result.data[0]).toEqual({ name: "Alice", age: 30, active: true });
|
|
expect(result.data[1]).toEqual({ name: "Bob", age: 25, active: false });
|
|
});
|
|
|
|
it("should parse CSV with int and float columns", () => {
|
|
const csv = [
|
|
"id,count,price",
|
|
"int,int,float",
|
|
"1,5,9.99",
|
|
"2,3,4.50",
|
|
].join("\n");
|
|
|
|
const result = parseCsv(csv, { emitTypes: false });
|
|
|
|
expect(result.data).toHaveLength(2);
|
|
expect(result.data[0]).toEqual({ id: 1, count: 5, price: 9.99 });
|
|
expect(result.data[1]).toEqual({ id: 2, count: 3, price: 4.5 });
|
|
});
|
|
|
|
it("should parse CSV with non-ASCII characters and comments", () => {
|
|
const csv = [
|
|
'# id: unique intent state ID (e.g. "仙人掌怪-boost")',
|
|
"id",
|
|
"string",
|
|
"仙人掌怪-boost",
|
|
"仙人掌怪-defend",
|
|
"仙人掌怪-attack",
|
|
].join("\n");
|
|
|
|
const result = parseCsv(csv, { emitTypes: false });
|
|
|
|
expect(result.data).toHaveLength(3);
|
|
expect(result.data[0]).toEqual({ id: "仙人掌怪-boost" });
|
|
expect(result.data[1]).toEqual({ id: "仙人掌怪-defend" });
|
|
expect(result.data[2]).toEqual({ id: "仙人掌怪-attack" });
|
|
});
|
|
|
|
it("should parse CSV with string literal columns (unquoted in CSV)", () => {
|
|
const csv = [
|
|
"name,status",
|
|
"string,'on' | 'off'",
|
|
"Alice,on",
|
|
"Bob,off",
|
|
].join("\n");
|
|
|
|
const result = parseCsv(csv, { emitTypes: false });
|
|
|
|
expect(result.data).toHaveLength(2);
|
|
expect(result.data[0]).toEqual({ name: "Alice", status: "on" });
|
|
expect(result.data[1]).toEqual({ name: "Bob", status: "off" });
|
|
});
|
|
|
|
it("should parse CSV with array columns", () => {
|
|
const csv = [
|
|
"name,tags",
|
|
"string,string[]",
|
|
"Alice,[dev; admin]",
|
|
"Bob,[user]",
|
|
].join("\n");
|
|
|
|
const result = parseCsv(csv, { emitTypes: false });
|
|
|
|
expect(result.data).toHaveLength(2);
|
|
expect(result.data[0]).toEqual({ name: "Alice", tags: ["dev", "admin"] });
|
|
expect(result.data[1]).toEqual({ name: "Bob", tags: ["user"] });
|
|
});
|
|
|
|
it("should parse CSV with tuple columns", () => {
|
|
const csv = [
|
|
"name,coords",
|
|
"string,[number; number]",
|
|
"Alice,[1; 2]",
|
|
"Bob,[3; 4]",
|
|
].join("\n");
|
|
|
|
const result = parseCsv(csv, { emitTypes: false });
|
|
|
|
expect(result.data).toHaveLength(2);
|
|
expect(result.data[0]).toEqual({ name: "Alice", coords: [1, 2] });
|
|
expect(result.data[1]).toEqual({ name: "Bob", coords: [3, 4] });
|
|
});
|
|
|
|
it("should require at least 2 rows (header + schema)", () => {
|
|
const csv = "name,age\nstring,number";
|
|
expect(() => parseCsv(csv, { emitTypes: false })).not.toThrow();
|
|
|
|
const csv1Row = "name,age";
|
|
expect(() => parseCsv(csv1Row, { emitTypes: false })).toThrow(
|
|
"at least 2 rows",
|
|
);
|
|
});
|
|
|
|
it("should throw if header and schema count mismatch", () => {
|
|
const csv = "name,age\nstring";
|
|
expect(() => parseCsv(csv, { emitTypes: false })).toThrow("does not match");
|
|
});
|
|
});
|