import { cleanup, screen } from "@testing-library/react"; import { afterEach, describe, expect, it } from "vitest"; import { createSchema, renderCanvasShell } from "./canvas-shell-test-utils"; afterEach(() => { cleanup(); }); describe("CanvasShell media rendering", () => { it("hides media when a parent layer group is hidden", () => { renderCanvasShell({ initialState: { layers: [ { collapsed: false, displayName: "Scene Group", id: "group-1", kind: "group", name: "scene-group", visible: false, }, { displayName: "Layer 1", id: "layer-1", kind: "layer", name: "layer-1", parentGroupId: "group-1", visible: true, }, ], mediaAssets: [ { dataUrl: "data:image/png;base64,test", fileName: "material.png", id: "media-1", layerId: "layer-1", mimeType: "image/png", position: { x: 0, y: 0 }, size: { height: 200, unit: "px", width: 300 }, }, ], selectedLayerId: "layer-1", }, schema: createSchema(), }); expect(screen.queryByRole("button", { name: "Select material.png" })).toBeNull(); }); it("hides unavailable image resources", () => { renderCanvasShell({ initialState: { layers: [ { displayName: "Unavailable", id: "unavailable-layer", kind: "layer", name: "unavailable", visible: true, }, ], mediaAssets: [ { assetKind: "image", error: { code: "binary-resource-unavailable", message: "The image resource is unavailable.", }, fileName: "unavailable.png", id: "unavailable-image", layerId: "unavailable-layer", lifecycle: "unavailable", mimeType: "image/png", position: { x: 0, y: 0 }, resourceRef: `media:image:sha256:${"b".repeat(64)}`, size: { height: 200, unit: "px", width: 300 }, }, ], }, schema: createSchema(), }); expect( screen.queryByRole("button", { name: "Select unavailable.png" }), ).toBeNull(); }); it("renders uploaded canvas images with cover crop and runtime transforms", () => { renderCanvasShell({ initialState: { layers: [ { displayName: "Layer 1", id: "layer-1", kind: "layer", name: "layer-1", visible: true, }, ], mediaAssets: [ { dataUrl: "data:image/png;base64,test", fileName: "material.png", id: "media-1", layerId: "layer-1", mimeType: "image/png", position: { x: 48, y: -24 }, size: { height: 200, unit: "px", width: 300 }, transform: { flipHorizontal: true, rotationDeg: 90 }, }, ], selectedLayerId: "layer-1", }, schema: createSchema(), }); const mediaButton = screen.getByRole("button", { name: "Select material.png" }); const mediaImage = screen.getByRole("img", { name: "material.png" }); expect(mediaButton.className).toContain("inset-0"); expect(mediaImage.className).toContain("object-cover"); expect(mediaImage.getAttribute("style")).toContain("rotate(90deg) scale(-1.5, 1.5)"); }); it("positions uploaded images by their own frame in infinite mode", () => { renderCanvasShell({ initialState: { canvas: { mode: "infinite", offset: { x: 0, y: 0 }, size: { height: 200, unit: "px", width: 300 }, zoom: 100, }, layers: [ { displayName: "Layer 1", id: "layer-1", kind: "layer", name: "layer-1", visible: true, }, ], mediaAssets: [ { dataUrl: "data:image/png;base64,test", fileName: "material.png", id: "media-1", layerId: "layer-1", mimeType: "image/png", position: { x: 48, y: -24 }, size: { height: 120, unit: "px", width: 240 }, transform: { flipHorizontal: true, rotationDeg: 90 }, }, ], }, schema: createSchema(), }); const mediaButton = screen.getByRole("button", { name: "Select material.png" }); const mediaImage = screen.getByRole("img", { name: "material.png" }); expect(mediaButton.style.left).toBe("-72px"); expect(mediaButton.style.top).toBe("-84px"); expect(mediaButton.style.width).toBe("240px"); expect(mediaButton.style.height).toBe("120px"); expect(mediaButton.style.transform).toContain("rotate(90deg) scale(-1, 1)"); expect(mediaImage.getAttribute("style")).toBeNull(); }); });