import { describe, it, expect } from "vitest"; import { parseCsv } from "../loader"; import * as path from "path"; import { fixturesDir, readFixture } from "../test-utils"; describe("parseCsv - references in combinatory schemas", () => { it("should resolve reference inside a tuple", () => { const csv = [ "id,info", "string,[ref: @users; note: string]", "1,[ref: 1; note: urgent]", ].join("\n"); const result = parseCsv(csv, { emitTypes: false, currentFilePath: path.join(fixturesDir, "test.csv"), }); expect(result.data).toHaveLength(1); const info = result.data[0].info as unknown[]; expect(info).toHaveLength(2); expect(info[0]).toEqual({ id: "1", name: "Alice", email: "alice@example.com", }); expect(info[1]).toBe("urgent"); }); it("should resolve reference array inside a tuple", () => { const csv = [ "id,info", "string,[refs: @users[]; note: string]", "1,[refs: [1; 2]; note: test]", ].join("\n"); const result = parseCsv(csv, { emitTypes: false, currentFilePath: path.join(fixturesDir, "test.csv"), }); expect(result.data).toHaveLength(1); const info = result.data[0].info as unknown[]; expect(info).toHaveLength(2); const refs = info[0] as Record[]; expect(refs).toHaveLength(2); expect(refs[0]).toEqual({ id: "1", name: "Alice", email: "alice@example.com", }); expect(refs[1]).toEqual({ id: "2", name: "Bob", email: "bob@example.com" }); expect(info[1]).toBe("test"); }); it("should resolve array of tuples containing references", () => { const csv = [ "id,pairs", "string,[@users; number][]", "1,[[1; 10]; [2; 20]]", ].join("\n"); const result = parseCsv(csv, { emitTypes: false, currentFilePath: path.join(fixturesDir, "test.csv"), }); expect(result.data).toHaveLength(1); const pairs = result.data[0].pairs as unknown[][]; expect(pairs).toHaveLength(2); expect(pairs[0]).toHaveLength(2); expect(pairs[0][0]).toEqual({ id: "1", name: "Alice", email: "alice@example.com", }); expect(pairs[0][1]).toBe(10); expect(pairs[1][0]).toEqual({ id: "2", name: "Bob", email: "bob@example.com", }); expect(pairs[1][1]).toBe(20); }); it("should resolve reference in union (@users | string)", () => { const csv = ["id,value", "string,@users | string", "1,1", "2,unknown"].join( "\n", ); const result = parseCsv(csv, { emitTypes: false, currentFilePath: path.join(fixturesDir, "test.csv"), }); expect(result.data).toHaveLength(2); expect(result.data[0].value).toEqual({ id: "1", name: "Alice", email: "alice@example.com", }); expect(result.data[1].value).toBe("unknown"); }); it("should resolve reference in union (@users[] | string)", () => { const csv = [ "id,value", "string,@users[] | string", "1,[1; 2]", "2,none", ].join("\n"); const result = parseCsv(csv, { emitTypes: false, currentFilePath: path.join(fixturesDir, "test.csv"), }); expect(result.data).toHaveLength(2); const arr = result.data[0].value as Record[]; expect(arr).toHaveLength(2); expect(arr[0]).toEqual({ id: "1", name: "Alice", email: "alice@example.com", }); expect(result.data[1].value).toBe("none"); }); it("should resolve array of reference unions (@users | @parts)[]", () => { const csv = ["id,items", "string,(@users | @parts)[]", "1,[1; 2]"].join( "\n", ); const result = parseCsv(csv, { emitTypes: false, currentFilePath: path.join(fixturesDir, "test.csv"), }); expect(result.data).toHaveLength(1); }); it("should resolve named tuple with reference and other fields", () => { const csv = [ "id,details", "string,[owner: @users; count: number]", "1,[owner: 1; count: 5]", ].join("\n"); const result = parseCsv(csv, { emitTypes: false, currentFilePath: path.join(fixturesDir, "test.csv"), }); expect(result.data).toHaveLength(1); const details = result.data[0].details as unknown[]; expect(details).toHaveLength(2); expect(details[0]).toEqual({ id: "1", name: "Alice", email: "alice@example.com", }); expect(details[1]).toBe(5); }); it("should parse encounter fixture with custom type aliases and nested tuples/arrays", () => { const encounterCsv = readFixture("encounter.csv"); const result = parseCsv(encounterCsv, { emitTypes: false, currentFilePath: path.join(fixturesDir, "encounter.csv"), }); expect(result.data).toHaveLength(2); // First row: cactus_pair expect(result.data[0]).toMatchObject({ id: "cactus_pair", type: "minion", name: "仙人掌怪", description: "概念:防+强化。【尖刺X】:对攻击者造成X点伤害。", dialogue: "", }); const cactusEnemies = result.data[0].enemies as unknown[]; expect(cactusEnemies).toHaveLength(2); expect(cactusEnemies[0]).toEqual(["仙人掌怪", 12, []]); expect(cactusEnemies[1]).toEqual(["仙人掌怪", 12, []]); // Second row: snake_pair expect(result.data[1]).toMatchObject({ id: "snake_pair", type: "minion", name: "蛇", description: "概念:攻+强化。给玩家塞入蛇毒牌(1费:打出时移除此牌。弃掉时受到3点伤害)。", dialogue: "", }); const snakeEnemies = result.data[1].enemies as unknown[]; expect(snakeEnemies).toHaveLength(1); expect(snakeEnemies[0]).toEqual([ "蛇", 10, [ ["poison", 2], ["quick", 1], ], ]); }); });