Skip to content
File

Blob: tests/e2e/specs/24-canvas-image-upload.spec.ts

typescript56 lines
1import { test, createTestPage, waitForCanvasSceneCount, waitForPersistedSnapshot } from "../fixtures/bland-test";
2 
3// Smallest legal PNG (1x1) as base64 — enough to validate the upload
4// round-trip without shipping a test asset.
5const TINY_PNG_BASE64 =
6 "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR4nGP4z8DwHwAFAAH/iZk9HQAAAABJRU5ErkJggg==";
7 
8test.describe("canvas page - images", () => {
9 test("dropping an image uploads + persists across reload via hydration", async ({
10 authenticatedPage: { page, accessToken },
11 e2eWorkspace,
12 }) => {
13 const testPage = await createTestPage(page, accessToken, "Canvas Image Upload", e2eWorkspace, "canvas");
14 
15 await page.goto(`/${testPage.workspaceSlug}/${testPage.pageId}`);
16 await page.locator(".excalidraw").waitFor({ state: "attached", timeout: 30_000 });
17 
18 // Drop a PNG onto the canvas. Excalidraw listens for drag-drop via
19 // document-level listeners, so dispatching a `drop` on the excalidraw
20 // root triggers its image-insertion flow.
21 const excalidrawRoot = page.locator(".excalidraw").first();
22 await excalidrawRoot.evaluate((root, base64) => {
23 const binary = atob(base64);
24 const bytes = new Uint8Array(binary.length);
25 for (let i = 0; i < binary.length; i += 1) bytes[i] = binary.charCodeAt(i);
26 const file = new File([bytes as BlobPart], "pixel.png", { type: "image/png" });
27 const dt = new DataTransfer();
28 dt.items.add(file);
29 const rect = root.getBoundingClientRect();
30 root.dispatchEvent(
31 new DragEvent("drop", {
32 bubbles: true,
33 cancelable: true,
34 clientX: rect.left + rect.width / 2,
35 clientY: rect.top + rect.height / 2,
36 dataTransfer: dt,
37 }),
38 );
39 }, TINY_PNG_BASE64);
40 
41 // Wait for the element to appear in the scene. Drop-to-scene goes through
42 // Excalidraw's own async readers, so give it a generous window.
43 await waitForCanvasSceneCount(page, 1);
44 
45 await waitForPersistedSnapshot(page, accessToken, testPage);
46 
47 await page.reload();
48 await page.locator(".excalidraw").waitFor({ state: "attached", timeout: 30_000 });
49 
50 // On reload, the binding reads yFileRefs and hydrates via
51 // fetchUploadAsDataURL → addFiles. The image element should re-appear
52 // in the scene.
53 await waitForCanvasSceneCount(page, 1);
54 });
55});