import { describe, expect, it } from 'vitest'; import { parseCsv, toCsv, validateCustomerRows } from '@/lib/csv'; describe('parseCsv', () => { it('parses a header and quoted fields', () => { const { header, rows } = parseCsv('name,email,company\n"Doe, Jane",jane@example.com,"Acme, Inc"\n'); expect(header).toEqual(['name', 'email', 'company']); expect(rows).toEqual([{ name: 'Doe, Jane', email: 'jane@example.com', company: 'Acme, Inc' }]); }); it('unescapes doubled quotes and tolerates CRLF', () => { const { rows } = parseCsv('a,b\r\n"say ""hi""",2\r\n'); expect(rows[0]).toEqual({ a: 'say "hi"', b: '2' }); }); it('ignores blank lines', () => { expect(parseCsv('a\n\n1\n').rows).toHaveLength(1); }); }); describe('validateCustomerRows', () => { const result = validateCustomerRows([ { name: 'Jane', email: 'JANE@Example.com', company: 'Acme', status: 'lead' }, { name: '', email: 'x@y.com', company: '', status: 'active' }, // missing name { name: 'Bob', email: 'not-an-email', company: '', status: 'active' }, // bad email { name: 'Ann', email: 'ann@example.com', company: '', status: 'vip' }, // bad status { name: 'Dup', email: 'jane@example.com', company: '', status: 'active' }, // duplicate email { name: 'Eve', email: 'eve@example.com', company: '', status: '' }, // empty status → active ]); it('normalizes email casing and fills the default status', () => { expect(result.valid[0]).toEqual({ name: 'Jane', email: 'jane@example.com', company: 'Acme', status: 'lead' }); expect(result.valid[1]).toEqual({ name: 'Eve', email: 'eve@example.com', company: '', status: 'active' }); }); it('reports one error per invalid row (line numbers are 1-based + header)', () => { expect(result.errors.map((e) => e.row)).toEqual([3, 4, 5]); }); it('flags duplicate emails within the file', () => { expect(result.duplicatesInFile).toEqual([6]); expect(result.total).toBe(6); expect(result.valid).toHaveLength(2); }); }); describe('toCsv', () => { it('escapes commas and quotes and keeps the column order', () => { expect(toCsv([{ a: 'x,y', b: 'say "hi"' }], ['a', 'b'])).toBe('a,b\n"x,y","say ""hi"""'); }); it('renders null/undefined as empty fields', () => { expect(toCsv([{ a: null, b: undefined }], ['a', 'b'])).toBe('a,b\n,'); }); });