import { describe, it, expect } from 'vitest'; import { parseCatalogCsv } from '@/budget/csv'; const HEADER = 'categoria,nombre,calidad,precio,unidad,descriptor_render,sku'; describe('parseCatalogCsv', () => { it('parsea filas válidas y convierte precio a céntimos', () => { const csv = [ HEADER, 'suelo,Cerámico gris,media,28.00,m2,suelo cerámico gris,SUE-M', 'mobiliario,Muebles cocina,premium,550,ml,muebles laminado roble,MOB-P', ].join('\n'); const { rows, errors } = parseCatalogCsv(csv); expect(errors).toHaveLength(0); expect(rows).toHaveLength(2); expect(rows[0]).toMatchObject({ categoria: 'suelo', calidad: 'media', precioUnit: 2800, unidad: 'm2', sku: 'SUE-M', }); expect(rows[1].precioUnit).toBe(55000); }); it('reporta errores por fila sin abortar las válidas', () => { const csv = [ HEADER, 'suelo,Bueno,media,28,m2,desc,SUE-M', 'inventada,Malo,media,10,m2,desc,X', // categoria inválida 'pared,Sin precio,media,abc,m2,desc,PAR-M', // precio no numérico ].join('\n'); const { rows, errors } = parseCatalogCsv(csv); expect(rows).toHaveLength(1); expect(errors).toHaveLength(2); expect(errors[0].line).toBe(3); // 1-indexed incluyendo cabecera expect(errors[1].line).toBe(4); }); it('devuelve error global si falta la cabecera esperada', () => { const { rows, errors } = parseCatalogCsv('a,b,c\n1,2,3'); expect(rows).toHaveLength(0); expect(errors[0].message).toMatch(/cabecera/i); }); });