/** * Unit tests for load_diagram's file parsing (load-diagram.ts). * * A .drawio file stores each page's either as plain XML or * as draw.io's compressed default (encodeURIComponent → raw deflate → * base64 text content). The loader must produce the canonical session * shape: an whose every page is plain XML. */ import { deflateRawSync } from "node:zlib" import { DOMParser } from "linkedom" import { beforeAll, describe, expect, it } from "vitest" // Install the DOM polyfills exactly as index.ts does at runtime. beforeAll(() => { ;(globalThis as any).DOMParser = DOMParser class XMLSerializerPolyfill { serializeToString(node: any): string { if (node.outerHTML !== undefined) return node.outerHTML if (node.documentElement) return node.documentElement.outerHTML return "" } } ;(globalThis as any).XMLSerializer = XMLSerializerPolyfill }) import { decompressPageContent, parseDrawioFileContent, } from "../src/load-diagram.js" const MODEL_XML = `` /** Compress a page body exactly the way draw.io does when saving. */ function drawioCompress(xml: string): string { return deflateRawSync( Buffer.from(encodeURIComponent(xml), "utf-8"), ).toString("base64") } const PLAIN_MXFILE = `${MODEL_XML}` const COMPRESSED_MXFILE = `${drawioCompress(MODEL_XML)}` describe("decompressPageContent", () => { it("round-trips draw.io's compressed format", () => { expect(decompressPageContent(drawioCompress(MODEL_XML))).toBe(MODEL_XML) }) it("handles non-URI-encoded legacy payloads", () => { const legacy = deflateRawSync(Buffer.from(MODEL_XML, "utf-8")).toString( "base64", ) expect(decompressPageContent(legacy)).toBe(MODEL_XML) }) it("returns null for garbage", () => { expect(decompressPageContent("not base64 deflate")).toBeNull() }) }) describe("parseDrawioFileContent", () => { it("passes a plain-XML mxfile through unchanged", () => { const r = parseDrawioFileContent(PLAIN_MXFILE) expect(r).toEqual({ ok: true, xml: PLAIN_MXFILE }) }) it("wraps a bare mxGraphModel into a one-page mxfile", () => { const r = parseDrawioFileContent(MODEL_XML) expect(r.ok).toBe(true) if (r.ok) { expect(r.xml).toContain(" { const r = parseDrawioFileContent(COMPRESSED_MXFILE) expect(r.ok).toBe(true) if (r.ok) { expect(r.xml).toContain(" { const mixed = `${MODEL_XML}${drawioCompress(MODEL_XML)}` const r = parseDrawioFileContent(mixed) expect(r.ok).toBe(true) if (r.ok) { const doc = new DOMParser().parseFromString(r.xml, "text/xml") const diagrams = Array.from( doc.querySelectorAll("diagram"), ) as Element[] expect(diagrams).toHaveLength(2) for (const d of diagrams) { expect(d.querySelector("mxGraphModel")).not.toBeNull() } } }) it("keeps empty pages as-is", () => { const withEmpty = `${MODEL_XML}` const r = parseDrawioFileContent(withEmpty) expect(r).toEqual({ ok: true, xml: withEmpty }) }) it("rejects empty files", () => { const r = parseDrawioFileContent(" ") expect(r.ok).toBe(false) }) it("rejects non-drawio content", () => { const r = parseDrawioFileContent("") expect(r.ok).toBe(false) if (!r.ok) expect(r.error).toContain("Not a draw.io file") }) it("rejects a page whose content is neither XML nor compressed", () => { const bad = `!!! not a diagram !!!` const r = parseDrawioFileContent(bad) expect(r.ok).toBe(false) if (!r.ok) expect(r.error).toContain('"Broken"') }) })