import pako from "pako"
import { describe, expect, it } from "vitest"
import {
pageModelXml,
pageSelectorFor,
placeOnPage,
replacePageModel,
} from "@/lib/diagram-pages"
const box = (id: string) =>
``
const model = (cells: string) =>
`${cells}`
const page = (id: string, cells: string) =>
`${model(cells)}`
const packedPage = (id: string, cells: string) => {
const packed = Buffer.from(
pako.deflateRaw(encodeURIComponent(model(cells))),
).toString("base64")
return `${packed}`
}
const TWO_PAGES = `${page("a", box("A"))}${page("b", box("B"))}`
const pagesOf = (xml: string) =>
Array.from(
new DOMParser()
.parseFromString(xml, "text/xml")
.getElementsByTagName("diagram"),
).map((d) => ({
id: d.getAttribute("id"),
name: d.getAttribute("name"),
cells: Array.from(d.getElementsByTagName("mxCell"))
.map((c) => c.getAttribute("id"))
.filter((id) => id !== "0" && id !== "1"),
}))
describe("pageModelXml", () => {
it("gives the page with the id, and the first page without one", () => {
expect(pageModelXml(TWO_PAGES, "b")).toContain('id="B"')
expect(pageModelXml(TWO_PAGES, "b")).not.toContain('id="A"')
expect(pageModelXml(TWO_PAGES, null)).toContain('id="A"')
expect(pageModelXml(TWO_PAGES, "missing")).toContain('id="A"')
})
it("inflates a compressed page and passes a bare model through", () => {
const file = `${page("a", box("A"))}${packedPage("b", box("B"))}`
expect(pageModelXml(file, "b")).toContain('id="B"')
expect(pageModelXml(model(box("Z")), "b")).toBe(model(box("Z")))
expect(pageModelXml(" {
it("selects the page only when the document has it", () => {
expect(pageSelectorFor(TWO_PAGES, "b")).toEqual({ page_id: "b" })
expect(pageSelectorFor(TWO_PAGES, "missing")).toEqual({})
expect(pageSelectorFor(TWO_PAGES, null)).toEqual({})
expect(pageSelectorFor(model(box("Z")), "b")).toEqual({})
})
})
describe("replacePageModel", () => {
it("replaces one page and keeps the others, the names and the variables", () => {
const result = replacePageModel(TWO_PAGES, "b", model(box("N")))
expect(pagesOf(result)).toEqual([
{ id: "a", name: "Page a", cells: ["A"] },
{ id: "b", name: "Page b", cells: ["N"] },
])
expect(result).toContain('vars="{"x":"1"}"')
})
it("falls back to the first page for an unknown or missing id", () => {
for (const id of ["missing", null]) {
const result = replacePageModel(TWO_PAGES, id, model(box("N")))
expect(pagesOf(result).map((p) => p.cells)).toEqual([["N"], ["B"]])
}
})
it("starts from the blank file when there is no document", () => {
for (const base of ["", "", " {
expect(() => replacePageModel(TWO_PAGES, "a", "")).toThrow()
})
})
describe("placeOnPage", () => {
it("puts one page's worth of drawing on the model's page", () => {
const drawn = `${model(box("N"))}`
const result = placeOnPage(drawn, TWO_PAGES, "b")
expect(pagesOf(result)).toEqual([
{ id: "a", name: "Page a", cells: ["A"] },
{ id: "b", name: "Page b", cells: ["N"] },
])
})
it("applies the drawn file's variables, and keeps the canvas's otherwise", () => {
const withVars = `${model(box("N"))}`
expect(placeOnPage(withVars, TWO_PAGES, "b")).toContain(
'vars="{"team":"New"}"',
)
const without = `${model(box("N"))}`
expect(placeOnPage(without, TWO_PAGES, "b")).toContain(
'vars="{"x":"1"}"',
)
})
it("lets a drawing with several pages replace the document", () => {
const drawn = `${page("x", box("X"))}${page("y", box("Y"))}`
expect(placeOnPage(drawn, TWO_PAGES, "b")).toBe(drawn)
})
it("draws on the blank file when the canvas is empty", () => {
const drawn = `${model(box("N"))}`
expect(pagesOf(placeOnPage(drawn, "", null))).toEqual([
{ id: "page-1", name: "Page-1", cells: ["N"] },
])
})
})