import { describe, expect, it } from 'vitest'; import { parseCsvData, expandVariants } from './variants.js'; import type { DefFile } from './types.js'; function defFile(name: string, text: string): DefFile { return { name, text, source: name, kind: 'csv' }; } describe('parseCsvData', () => { it('parses the spec example with an empty array', () => { const csv = [ 'name,parents', 'string,string[]', 'clark,[jonathan;martha]', 'bruce,[]', ].join('\n'); const { rows, header } = parseCsvData(csv, 'test'); expect(header).toEqual(['name', 'parents']); expect(rows).toEqual([ { name: 'clark', parents: ['jonathan', 'martha'] }, { name: 'bruce', parents: [] }, ]); }); it('parses a crop tuple', () => { const csv = [ 'id,faceCrop', 'string,[number;number;number;number]', 'fish,[0;0;5;2]', 'grain,[1;0;5;2]', ].join('\n'); const { rows } = parseCsvData(csv, 'test'); expect(rows).toEqual([ { id: 'fish', faceCrop: [0, 0, 5, 2] }, { id: 'grain', faceCrop: [1, 0, 5, 2] }, ]); }); it('throws a BgmError on a type mismatch', () => { const csv = ['n', 'number', 'not-a-number'].join('\n'); expect(() => parseCsvData(csv, 'test')).toThrow(/Invalid CSV/); }); it('allows a header and schema with no data rows', () => { const { rows } = parseCsvData('a\nstring', 'test'); expect(rows).toEqual([]); }); }); describe('expandVariants', () => { it('parses inline CSV when the value contains a newline', () => { const rows = expandVariants('a,b\nstring,number\nx,1', 'pkg/def.yaml', new Map(), 'src'); expect(rows).toEqual([{ a: 'x', b: 1 }]); }); it('resolves a path against the def file directory', () => { const defs = new Map([ ['pkg/parts/seats.csv', [defFile('pkg/parts/seats.csv', 'seat\nnumber\n0\n1')]], ]); const rows = expandVariants('./seats.csv', 'pkg/parts/board.yaml', defs, 'src'); expect(rows).toEqual([{ seat: 0 }, { seat: 1 }]); }); it('throws when the referenced csv is missing', () => { expect(() => expandVariants('./nope.csv', 'pkg/def.yaml', new Map(), 'src')).toThrow( /CSV not found/, ); }); it('throws when $variants is not a string', () => { expect(() => expandVariants(42, 'pkg/def.yaml', new Map(), 'src')).toThrow( /must be a path or inline CSV/, ); }); });