forked from bots-garden/ori
| ✨ Workspace panel, selectors, previews, desktop app, sandbox template, resizable file tree, light/dark theme | 1 | import { act, render, screen } from "@testing-library/react"; |
| 2 | import { describe, expect, it, vi } from "vitest"; | |
| 3 | import { DRAWIO_EMBED_URL, DrawioView } from "./DrawioView"; | |
| 4 | ||
| 5 | /** viewerSays simulates one postMessage frame coming from the iframe. */ | |
| 6 | function viewerSays(frame: HTMLIFrameElement, payload: unknown) { | |
| 7 | act(() => { | |
| 8 | window.dispatchEvent( | |
| 9 | new MessageEvent("message", { | |
| 10 | data: typeof payload === "string" ? payload : JSON.stringify(payload), | |
| 11 | source: frame.contentWindow, | |
| 12 | }), | |
| 13 | ); | |
| 14 | }); | |
| 15 | } | |
| 16 | ||
| 17 | describe("DrawioView", () => { | |
| 18 | it("points the iframe at the read-only embed viewer", () => { | |
| 19 | render(<DrawioView xml="<mxfile/>" />); | |
| 20 | const frame = screen.getByTitle("draw.io diagram") as HTMLIFrameElement; | |
| 21 | expect(frame.getAttribute("src")).toBe(DRAWIO_EMBED_URL); | |
| 22 | expect(DRAWIO_EMBED_URL).toContain("embed.diagrams.net"); | |
| 23 | expect(DRAWIO_EMBED_URL).toContain("proto=json"); | |
| 24 | expect(screen.getByText("loading viewer…")).toBeDefined(); | |
| 25 | }); | |
| 26 | ||
| 27 | it("answers the viewer's init with a load action carrying the XML", () => { | |
| 28 | render(<DrawioView xml="<mxfile><diagram/></mxfile>" timeoutMs={60000} />); | |
| 29 | const frame = screen.getByTitle("draw.io diagram") as HTMLIFrameElement; | |
| 30 | const target = frame.contentWindow; | |
| 31 | if (!target) { | |
| 32 | throw new Error("jsdom iframe has no contentWindow"); | |
| 33 | } | |
| 34 | const posted = vi.spyOn(target, "postMessage"); | |
| 35 | ||
| 36 | viewerSays(frame, "not json"); | |
| 37 | expect(posted).not.toHaveBeenCalled(); | |
| 38 | ||
| 39 | viewerSays(frame, { event: "init" }); | |
| 40 | expect(posted).toHaveBeenCalledTimes(1); | |
| 41 | expect(JSON.parse(String(posted.mock.calls[0][0]))).toEqual({ | |
| 42 | action: "load", | |
| 43 | xml: "<mxfile><diagram/></mxfile>", | |
| 44 | autosave: 0, | |
| 45 | }); | |
| 46 | expect(screen.queryByText("loading viewer…")).toBeNull(); | |
| 47 | expect(frame.hidden).toBe(false); | |
| 48 | }); | |
| 49 | ||
| 50 | it("ignores messages from other windows", () => { | |
| 51 | render(<DrawioView xml="<mxfile/>" timeoutMs={60000} />); | |
| 52 | act(() => { | |
| 53 | window.dispatchEvent( | |
| 54 | new MessageEvent("message", { | |
| 55 | data: JSON.stringify({ event: "init" }), | |
| 56 | source: window, | |
| 57 | }), | |
| 58 | ); | |
| 59 | }); | |
| 60 | expect(screen.getByText("loading viewer…")).toBeDefined(); | |
| 61 | }); | |
| 62 | ||
| 63 | it("falls back to a notice when the viewer never answers", async () => { | |
| 64 | render(<DrawioView xml="<mxfile/>" timeoutMs={20} />); | |
| 65 | await act(async () => { | |
| 66 | await new Promise((resolve) => setTimeout(resolve, 60)); | |
| 67 | }); | |
| 68 | expect(screen.getByText(/is not reachable/)).toBeDefined(); | |
| 69 | expect( | |
| 70 | (screen.getByTitle("draw.io diagram") as HTMLIFrameElement).hidden, | |
| 71 | ).toBe(true); | |
| 72 | }); | |
| 73 | }); |