- Enhanced cursor behavior for new tools: semantic select, mask lasso, and mask rectangle. - Updated mask edit state to include mask asset ID and kind. - Implemented inpaint region commands for adding, applying, and removing inpaint regions. - Introduced new operations for lasso and semantic selection tools. - Created UI components for candidate review and inpaint region management. - Added tests for inpaint region commands to ensure functionality. - Updated various components to support new inpaint features and improve user experience.
211 lines
5.6 KiB
TypeScript
211 lines
5.6 KiB
TypeScript
import { describe, expect, test } from "bun:test";
|
|
import { createInitialAppState } from "@editor/initial-state";
|
|
import type { AppState } from "@editor/state";
|
|
import { canvasRenderFramesEqual, selectCanvasRenderFrame } from "./renderFrame";
|
|
|
|
describe("canvas render frame selection", () => {
|
|
test("ignores non-visual tool and history state", () => {
|
|
const state = createInitialAppState("Test");
|
|
const next: AppState = {
|
|
...state,
|
|
editor: {
|
|
...state.editor,
|
|
tools: {
|
|
...state.editor.tools,
|
|
generate: {
|
|
...state.editor.tools.generate,
|
|
prompt: "new prompt",
|
|
steps: state.editor.tools.generate.steps + 1,
|
|
},
|
|
chromaKey: {
|
|
...state.editor.tools.chromaKey,
|
|
tolerance: state.editor.tools.chromaKey.tolerance + 1,
|
|
},
|
|
magicWand: {
|
|
...state.editor.tools.magicWand,
|
|
contiguous: !state.editor.tools.magicWand.contiguous,
|
|
},
|
|
},
|
|
},
|
|
history: { past: [{ document: state.document, editor: state.editor }], future: [] },
|
|
};
|
|
|
|
expect(canvasRenderFramesEqual(selectCanvasRenderFrame(state), selectCanvasRenderFrame(next))).toBe(true);
|
|
});
|
|
|
|
test("detects document changes", () => {
|
|
const state = createInitialAppState("Test");
|
|
const next = {
|
|
...state,
|
|
document: {
|
|
...state.document,
|
|
name: "Changed",
|
|
},
|
|
};
|
|
|
|
expect(canvasRenderFramesEqual(selectCanvasRenderFrame(state), selectCanvasRenderFrame(next))).toBe(false);
|
|
});
|
|
|
|
test("compares stable visual editor fields structurally", () => {
|
|
const state = createInitialAppState("Test");
|
|
const sameSelectionValues = {
|
|
...state,
|
|
editor: {
|
|
...state.editor,
|
|
selection: {
|
|
artboardId: state.editor.selection.artboardId,
|
|
layerIds: [...state.editor.selection.layerIds],
|
|
},
|
|
},
|
|
};
|
|
const changedBrush = {
|
|
...state,
|
|
editor: {
|
|
...state.editor,
|
|
tools: {
|
|
...state.editor.tools,
|
|
brush: {
|
|
...state.editor.tools.brush,
|
|
size: state.editor.tools.brush.size + 1,
|
|
},
|
|
},
|
|
},
|
|
};
|
|
const changedPreview = {
|
|
...state,
|
|
editor: {
|
|
...state.editor,
|
|
brushPreview: { position: { x: 10, y: 20 } },
|
|
},
|
|
};
|
|
|
|
expect(canvasRenderFramesEqual(selectCanvasRenderFrame(state), selectCanvasRenderFrame(sameSelectionValues))).toBe(true);
|
|
expectFrameChanged(state, changedBrush);
|
|
expectFrameChanged(state, changedPreview);
|
|
});
|
|
|
|
for (const [name, change] of visualEditorChanges) {
|
|
test(`detects ${name} changes`, () => {
|
|
const state = createInitialAppState("Test");
|
|
expectFrameChanged(state, change(state));
|
|
});
|
|
}
|
|
});
|
|
|
|
const visualEditorChanges: Array<[string, (state: AppState) => AppState]> = [
|
|
[
|
|
"viewport",
|
|
(state) => ({
|
|
...state,
|
|
editor: {
|
|
...state.editor,
|
|
viewport: {
|
|
...state.editor.viewport,
|
|
center: { x: state.editor.viewport.center.x + 1, y: state.editor.viewport.center.y },
|
|
},
|
|
},
|
|
}),
|
|
],
|
|
[
|
|
"selection",
|
|
(state) => ({
|
|
...state,
|
|
editor: {
|
|
...state.editor,
|
|
selection: { artboardId: "artboard", layerIds: ["layer"] },
|
|
},
|
|
}),
|
|
],
|
|
[
|
|
"transform session",
|
|
(state) => ({
|
|
...state,
|
|
editor: {
|
|
...state.editor,
|
|
transformSession: {
|
|
target: { type: "artboard", id: "artboard" },
|
|
handle: "body",
|
|
startPoint: { x: 1, y: 2 },
|
|
initialBounds: { x: 0, y: 0, w: 100, h: 80 },
|
|
},
|
|
},
|
|
}),
|
|
],
|
|
[
|
|
"mask edit",
|
|
(state) => ({
|
|
...state,
|
|
editor: {
|
|
...state.editor,
|
|
maskEdit: { kind: "layerMask", targetLayerId: "target", maskLayerId: "mask", maskAssetId: "mask-asset", viewMode: "overlay" },
|
|
},
|
|
}),
|
|
],
|
|
[
|
|
"brush stroke preview",
|
|
(state) => ({
|
|
...state,
|
|
editor: {
|
|
...state.editor,
|
|
brushStrokePreview: { layerId: "layer", assetId: "asset", source: "preview" },
|
|
},
|
|
}),
|
|
],
|
|
[
|
|
"generation candidate preview",
|
|
(state) => ({
|
|
...state,
|
|
editor: {
|
|
...state.editor,
|
|
generation: {
|
|
...state.editor.generation,
|
|
candidates: [
|
|
{
|
|
id: "candidate",
|
|
source: "data:image/png;base64,candidate",
|
|
mimeType: "image/png",
|
|
intrinsicSize: { w: 64, h: 64 },
|
|
mode: "text-to-image",
|
|
settings: state.editor.tools.generate,
|
|
seed: 12,
|
|
width: 64,
|
|
height: 64,
|
|
placement: {
|
|
artboardId: "artboard",
|
|
layerName: "Candidate",
|
|
transform: { position: { x: 1, y: 2 }, scale: { x: 1, y: 1 }, rotation: 0 },
|
|
},
|
|
},
|
|
],
|
|
selectedCandidateId: "candidate",
|
|
compareMode: "result",
|
|
},
|
|
},
|
|
}),
|
|
],
|
|
[
|
|
"active tool",
|
|
(state) => ({
|
|
...state,
|
|
editor: {
|
|
...state.editor,
|
|
tools: { ...state.editor.tools, activeTool: "brush" },
|
|
},
|
|
}),
|
|
],
|
|
[
|
|
"interaction mode",
|
|
(state) => ({
|
|
...state,
|
|
editor: {
|
|
...state.editor,
|
|
tools: { ...state.editor.tools, interactionMode: { type: "temporary-pan", previousTool: "select" } },
|
|
},
|
|
}),
|
|
],
|
|
];
|
|
|
|
function expectFrameChanged(previous: AppState, next: AppState) {
|
|
expect(canvasRenderFramesEqual(selectCanvasRenderFrame(previous), selectCanvasRenderFrame(next))).toBe(false);
|
|
}
|