templates2.Admin.Next/tests/unit/csv.test.ts

56 lines
2.3 KiB
TypeScript
Raw Permalink Normal View History

2026-10-11 20:25:34 +00:00
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,');
});
});