import { describe, expect, test } from "bun:test";
import { docxToHtml } from "../src/optional/docx.ts";
import { readWorkbook } from "../src/optional/sheet.ts";
import { listZip } from "../src/optional/zip.ts";
import { zipSync, strToU8 } from "fflate";
/**
* These exercise the parsers themselves. The browser wiring — one runtime asset
* per installed package, fetched on first use — is covered in component.test.ts.
*/
describe("zip listing", () => {
const archive = zipSync({
"docs/readme.md": strToU8("hello world\n".repeat(20)),
"src/index.ts": strToU8("export const value = 1;\n"),
});
test("entries are listed with their uncompressed sizes", async () => {
const entries = await listZip(archive);
expect(entries.map((entry) => entry.name).sort()).toEqual(["docs/readme.md", "src/index.ts"]);
expect(entries.find((entry) => entry.name === "docs/readme.md")!.size).toBe(240);
});
test("a corrupt archive rejects rather than resolving empty", async () => {
await expect(listZip(new Uint8Array([0x50, 0x4b, 3, 4, 9, 9, 9]))).rejects.toThrow();
});
});
describe("workbook reading", () => {
// Built with the same shape as examples/basic-app/public/viewer/sample.xlsx.
const NS = "http://schemas.openxmlformats.org/spreadsheetml/2006/main";
const R = "http://schemas.openxmlformats.org/officeDocument/2006/relationships";
const sheet = (rows: (string | number)[][]) =>
`${rows
.map(
(row, rowIndex) =>
`${row
.map((value, index) => {
const ref = `${String.fromCharCode(65 + index)}${rowIndex + 1}`;
return typeof value === "number"
? `${value}`
: `${value}`;
})
.join("")}
`,
)
.join("")}`;
const workbook = zipSync({
"[Content_Types].xml": strToU8(
'' +
'' +
'' +
'' +
'' +
'' +
"",
),
"_rels/.rels": strToU8(
``,
),
"xl/workbook.xml": strToU8(
`` +
'' +
'' +
"",
),
"xl/_rels/workbook.xml.rels": strToU8(
`` +
`` +
`` +
"",
),
"xl/worksheets/sheet1.xml": strToU8(
sheet([
["Region", "Q1"],
["North", 15400],
["South", 11200],
]),
),
"xl/worksheets/sheet2.xml": strToU8(
sheet([
["Team", "People"],
["Engineering", 42],
]),
),
});
test("every sheet comes back named, with a header and string cells", () => {
const sheets = readWorkbook(workbook);
expect(sheets.map((item) => item.name)).toEqual(["Revenue", "Headcount"]);
expect(sheets[0]!.header).toEqual(["Region", "Q1"]);
expect(sheets[0]!.rows).toEqual([
["North", "15400"],
["South", "11200"],
]);
expect(sheets[1]!.rows).toEqual([["Engineering", "42"]]);
});
});
describe("document conversion", () => {
const W = "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
const R = "http://schemas.openxmlformats.org/officeDocument/2006/relationships";
const paragraph = (text: string, style?: string) =>
`${style ? `` : ""}` +
`${text}`;
const document = zipSync({
"[Content_Types].xml": strToU8(
'' +
'' +
'' +
'' +
"",
),
"_rels/.rels": strToU8(
``,
),
"word/document.xml": strToU8(
`` +
paragraph("Quarterly summary", "Heading1") +
paragraph("Bodies of text survive; page layout does not.") +
"",
),
});
test("a docx becomes semantic HTML", async () => {
const html = await docxToHtml(document);
expect(html).toContain("
Quarterly summary
");
expect(html).toContain("Bodies of text survive");
// Semantic output only: no document chrome, and nothing executable.
expect(html).not.toContain("