Files
COMERCIAL-GTI/tests/csv.test.mjs
T
DESKTOP-F2O4A80\UserandClaude b8d10b210c Commit inicial: GTI Maquina Comercial
App local (Node + SQLite) para captura, tratamento e exportacao de leads
comerciais, com dashboard de gestao, login/usuarios e integracao Z-PRO.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-12 14:22:21 -03:00

91 lines
3.0 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import test from 'node:test';
import assert from 'node:assert/strict';
import fs from 'node:fs/promises';
import path from 'node:path';
import os from 'node:os';
import { splitCsvLine, csvEscape, excelTextCell, streamCsvRows, createCsvWriter, stripBom, BOM } from '../src/util/csv.mjs';
test('splitCsvLine separa campos com separador dentro de aspas', () => {
assert.deepEqual(splitCsvLine('a;"b;c";d'), ['a', 'b;c', 'd']);
});
test('splitCsvLine trata aspas duplas escapadas', () => {
assert.deepEqual(splitCsvLine('"x""y";z'), ['x"y', 'z']);
});
test('splitCsvLine aceita separador virgula', () => {
assert.deepEqual(splitCsvLine('a,b,"c,d"', ','), ['a', 'b', 'c,d']);
});
test('csvEscape protege valores com separador, aspas e quebra de linha', () => {
assert.equal(csvEscape('sem risco'), 'sem risco');
assert.equal(csvEscape('a;b'), '"a;b"');
assert.equal(csvEscape('diz "oi"'), '"diz ""oi"""');
assert.equal(csvEscape(null), '');
});
test('excelTextCell gera formula de texto para numeros longos', () => {
assert.equal(excelTextCell('557193335451'), '"=""557193335451"""');
});
test('stripBom remove BOM apenas quando presente', () => {
assert.equal(stripBom('abc'), 'abc');
assert.equal(stripBom('abc'), 'abc');
});
test('streamCsvRows le arquivo com BOM, auto-detecta separador e normaliza headers', async () => {
const file = path.join(os.tmpdir(), `gti-test-csv-${Date.now()}.csv`);
await fs.writeFile(file, `${BOM}Nome Empresa;Telefone 1\n"ACME; Ltda";7599999\nBeta;`, 'utf8');
try {
const rows = [];
for await (const row of streamCsvRows(file, {
normalizeHeader: (h) => h.toLowerCase().replace(/\s+/g, '_')
})) {
rows.push(row);
}
assert.equal(rows.length, 2);
assert.equal(rows[0].nome_empresa, 'ACME; Ltda');
assert.equal(rows[0].telefone_1, '7599999');
assert.equal(rows[1].telefone_1, '');
} finally {
await fs.rm(file, { force: true });
}
});
test('streamCsvRows suporta campo com quebra de linha dentro de aspas', async () => {
const file = path.join(os.tmpdir(), `gti-test-csvml-${Date.now()}.csv`);
await fs.writeFile(file, 'a;b\n1;"linha um\nlinha dois"\n2;simples', 'utf8');
try {
const rows = [];
for await (const row of streamCsvRows(file)) rows.push(row);
assert.equal(rows.length, 2);
assert.equal(rows[0].b, 'linha um\nlinha dois');
assert.equal(rows[1].b, 'simples');
} finally {
await fs.rm(file, { force: true });
}
});
test('createCsvWriter grava BOM, header e linhas', async () => {
const file = path.join(os.tmpdir(), `gti-test-csvw-${Date.now()}.csv`);
const writer = createCsvWriter(file, ['a', 'b']);
writer.writeRow(['1', csvEscape('x;y')]);
writer.writeRow(['2', excelTextCell('123')]);
await writer.end();
try {
const content = await fs.readFile(file, 'utf8');
assert.ok(content.startsWith(BOM));
const lines = stripBom(content).trim().split('\n');
assert.equal(lines[0], 'a;b');
assert.equal(lines[1], '1;"x;y"');
assert.equal(lines[2], '2;"=""123"""');
} finally {
await fs.rm(file, { force: true });
}
});