84 lines
2.4 KiB
TypeScript
84 lines
2.4 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import {
|
|
MAX_BROWSER_SPREADSHEET_BYTES,
|
|
assertSpreadsheetFile,
|
|
parseSpreadsheet,
|
|
} from "./excel.js";
|
|
|
|
async function createWorkbookFile(
|
|
rows: unknown[][],
|
|
fileName = "spreadsheet.xlsx",
|
|
): Promise<File> {
|
|
const ExcelJS = await import("exceljs");
|
|
const workbook = new ExcelJS.Workbook();
|
|
const worksheet = workbook.addWorksheet("Sheet1");
|
|
|
|
for (const row of rows) {
|
|
worksheet.addRow(row);
|
|
}
|
|
|
|
const buffer = await workbook.xlsx.writeBuffer();
|
|
return new File([buffer], fileName, {
|
|
type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
});
|
|
}
|
|
|
|
describe("excel import helpers", () => {
|
|
it("parses csv files with quoted values and skips blank rows", async () => {
|
|
const file = new File(
|
|
['name,role\n"Alice, A.",Engineer\n\nBob,Producer\n'],
|
|
"people.csv",
|
|
{ type: "text/csv" },
|
|
);
|
|
|
|
await expect(parseSpreadsheet(file)).resolves.toEqual([
|
|
{ name: "Alice, A.", role: "Engineer" },
|
|
{ name: "Bob", role: "Producer" },
|
|
]);
|
|
});
|
|
|
|
it("parses xlsx files and normalizes date cells to ISO strings", async () => {
|
|
const file = await createWorkbookFile([
|
|
["name", "startDate", "active"],
|
|
["Alice", new Date("2026-03-30T09:15:00.000Z"), true],
|
|
]);
|
|
|
|
await expect(parseSpreadsheet(file)).resolves.toEqual([
|
|
{
|
|
name: "Alice",
|
|
startDate: "2026-03-30T09:15:00.000Z",
|
|
active: "true",
|
|
},
|
|
]);
|
|
});
|
|
|
|
it("rejects duplicate headers in xlsx imports", async () => {
|
|
const file = await createWorkbookFile([
|
|
["Name", "name"],
|
|
["Alice", "Producer"],
|
|
]);
|
|
|
|
await expect(parseSpreadsheet(file)).rejects.toThrow('duplicate header "name"');
|
|
});
|
|
|
|
it("rejects legacy .xls uploads before parsing", () => {
|
|
const file = new File(["legacy"], "legacy.xls", {
|
|
type: "application/vnd.ms-excel",
|
|
});
|
|
|
|
expect(() => assertSpreadsheetFile(file)).toThrow(
|
|
"Legacy .xls files are not supported.",
|
|
);
|
|
});
|
|
|
|
it("rejects oversized spreadsheet uploads before parsing", () => {
|
|
const file = new File([Buffer.alloc(MAX_BROWSER_SPREADSHEET_BYTES + 1)], "oversized.xlsx", {
|
|
type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
});
|
|
|
|
expect(() => assertSpreadsheetFile(file)).toThrow(
|
|
`The selected file exceeds the ${MAX_BROWSER_SPREADSHEET_BYTES} byte limit`,
|
|
);
|
|
});
|
|
});
|