import { describe, expect, test } from "bun:test"; import type { ImageDocument } from "@core/document"; import { initialToolState } from "@editor/tools"; import { checkGenerationPreconditions } from "./preconditions"; describe("generation preconditions", () => { test("allows text-to-image with a prompt and artboard but no layer selection", () => { expect(checkGenerationPreconditions(document(), { artboardId: "artboard", layerIds: [] }, settings("text-to-image"))).toEqual({ ready: true }); }); test("requires exactly one source layer for image-to-image and outpaint", () => { const selection = { artboardId: "artboard", layerIds: [] }; expect(checkGenerationPreconditions(document(), selection, settings("image-to-image"))).toEqual({ ready: false, message: "Select exactly one image or raster layer for image-to-image generation." }); expect(checkGenerationPreconditions(document(), selection, settings("outpaint"))).toEqual({ ready: false, message: "Select exactly one image or raster layer to outpaint." }); }); test("requires an enabled mask for inpaint", () => { expect(checkGenerationPreconditions(document(), selected(), settings("inpaint"))).toEqual({ ready: false, message: "Paint a mask over the area you want AI to replace.", repair: "add-mask" }); }); test("allows inpaint when the selected source has an aligned enabled mask", () => { expect(checkGenerationPreconditions(document(true), selected(), settings("inpaint"))).toEqual({ ready: true }); }); test("explains prompt and outpaint-padding requirements", () => { expect(checkGenerationPreconditions(document(), selected(), { ...settings("image-to-image"), prompt: " " })).toEqual({ ready: false, message: "Enter a prompt to generate an image." }); expect(checkGenerationPreconditions(document(), selected(), { ...settings("outpaint"), outpaint: { left: 0, top: 0, right: 0, bottom: 0, feathering: 0 } })).toEqual({ ready: false, message: "Add outpaint padding on at least one side.", repair: "set-outpaint-padding" }); }); }); function settings(mode: "text-to-image" | "image-to-image" | "inpaint" | "outpaint") { return { ...initialToolState.generate, mode, prompt: "A lighthouse" }; } function selected() { return { artboardId: "artboard" as const, layerIds: ["source"] }; } function document(masked = false): ImageDocument { const transform = { position: { x: 0, y: 0 }, scale: { x: 1, y: 1 }, rotation: 0 }; return { id: "document", name: "Test", version: 1, assets: [ { id: "source-asset", name: "Source", mimeType: "image/png", source: "source", intrinsicSize: { w: 100, h: 100 } }, { id: "mask-asset", name: "Mask", mimeType: "image/png", source: "mask", intrinsicSize: { w: 100, h: 100 } }, ], artboards: [{ id: "artboard", name: "Artboard", bounds: { x: 0, y: 0, w: 100, h: 100 }, backgroundColor: "transparent", visible: true, locked: false, layers: [ { id: "mask", type: "raster", name: "Mask", visible: true, locked: false, opacity: 1, assetId: "mask-asset", transform }, { id: "source", type: "raster", name: "Source", visible: true, locked: false, opacity: 1, assetId: "source-asset", transform, layerMask: masked ? { kind: "raster", maskLayerId: "mask", enabled: true, inverted: false } : undefined, }, ], }], }; }