import { describe, expect, test } from "bun:test"; import type { ImageDocument } from "@core/document"; import type { Layer } from "@core/layer"; import { createDocumentReadIndex, forEachLayerBackToFront, resolveIndexedLayerBounds } from "./document-indexes"; const document: ImageDocument = { id: "d1", name: "Indexed Document", version: 1, assets: [ { id: "asset-target", name: "Target", mimeType: "image/png", source: "asset://target", intrinsicSize: { w: 100, h: 50 } }, { id: "asset-mask", name: "Mask", mimeType: "image/png", source: "asset://mask", intrinsicSize: { w: 100, h: 50 } }, { id: "asset-nested", name: "Nested", mimeType: "image/png", source: "asset://nested", intrinsicSize: { w: 20, h: 10 } }, ], artboards: [ { id: "a1", name: "Artboard", bounds: { x: 0, y: 0, w: 400, h: 300 }, backgroundColor: "transparent", visible: true, locked: false, layers: [ raster("mask", "Mask", "asset-mask"), { ...raster("target", "Target", "asset-target", { x: 10, y: 20 }, { x: 0.5, y: 0.5 }), layerMask: { kind: "raster", maskLayerId: "mask", enabled: true, inverted: false }, }, group("group", "Group", [ raster("nested-mask", "Nested Mask", "asset-mask"), { ...raster("nested-target", "Nested Target", "asset-nested", { x: 80, y: 10 }, { x: 2, y: 3 }), clippingMask: { maskLayerId: "nested-mask" } }, ]), ], }, ], }; describe("document read indexes", () => { test("indexes assets, layers, layer info, masks, and display counts", () => { const index = createDocumentReadIndex(document); expect(index.assetById.get("asset-target")).toBe(document.assets[0]); expect(index.layerById.get("nested-target")?.name).toBe("Nested Target"); expect(index.layerInfoById.get("target")).toMatchObject({ artboardId: "a1", index: 1 }); expect(index.layerInfoById.get("nested-target")).toMatchObject({ artboardId: "a1", parentGroupId: "group", index: 1 }); expect(index.maskLayerIds).toEqual(new Set(["mask", "nested-mask"])); expect(index.maskLayerIdsByArtboardId.get("a1")).toEqual(new Set(["mask", "nested-mask"])); expect(index.maskLayerIdsByLayerList.get(document.artboards[0]!.layers)).toEqual(new Set(["mask", "nested-mask"])); expect(index.maskLayerIdsByLayerList.get(groupLayer(document, "group").children)).toEqual(new Set(["nested-mask"])); expect(index.displayLayerCountByArtboardId.get("a1")).toBe(3); }); test("resolves layer bounds from indexed assets without scanning the document", () => { const index = createDocumentReadIndex(document); expect(resolveIndexedLayerBounds(index, "target")).toEqual({ x: 10, y: 20, w: 50, h: 25 }); expect(resolveIndexedLayerBounds(index, "group")).toEqual({ x: 0, y: 0, w: 120, h: 50 }); expect(resolveIndexedLayerBounds(index, raster("missing", "Missing", "missing-asset"))).toBeUndefined(); }); test("visits layers back to front without mutating source order", () => { const layers = document.artboards[0]!.layers; const visited: string[] = []; forEachLayerBackToFront(layers, (layer) => visited.push(layer.id)); expect(visited).toEqual(["group", "target", "mask"]); expect(layers.map((layer) => layer.id)).toEqual(["mask", "target", "group"]); }); }); function raster( id: string, name: string, assetId: string, position = { x: 0, y: 0 }, scale = { x: 1, y: 1 }, ): Extract { return { id, type: "raster", name, visible: true, locked: false, opacity: 1, assetId, transform: { position, scale, rotation: 0 }, }; } function group(id: string, name: string, children: Layer[]): Extract { return { id, type: "group", name, visible: true, locked: false, opacity: 1, transform: { position: { x: 0, y: 0 }, scale: { x: 1, y: 1 }, rotation: 0 }, children, }; } function groupLayer(document: ImageDocument, id: string): Extract { const layer = document.artboards[0]!.layers.find((candidate) => candidate.id === id); if (!layer || layer.type !== "group") throw new Error(`Missing group ${id}`); return layer; }