import { describe, expect, it } from "vitest"; import { defineToolcraft } from "../schema/define-toolcraft"; import { createToolcraftState } from "./create-template-state"; import { isToolcraftControlsResetHistoryPatch } from "./history-patch-metadata"; import { fileMediaAsset, imageMediaAsset, importImageMedia, } from "./reducer-media-test-utils"; import { toolcraftReducer } from "./reducer"; describe("toolcraftReducer media reset", () => { it("clears single-layer fileDrop media on global reset", () => { const app = defineToolcraft({ canvas: { enabled: true, upload: true }, panels: { controls: { sections: [ { controls: { source: { defaultValue: null, target: "media.source", type: "fileDrop", }, }, title: "Source", }, ], title: "Controls", }, }, }); const imported = importImageMedia(createToolcraftState(app), { sourceTarget: "media.source", }); const state = toolcraftReducer(imported, { type: "controls.reset" }); const undone = toolcraftReducer(state, { type: "history.undo" }); const redone = toolcraftReducer(undone, { type: "history.redo" }); expect(imported.mediaAssets).toHaveLength(1); expect(state.mediaAssets).toEqual([]); expect(state.values["media.source"]).toBeUndefined(); expect(undone.mediaAssets).toEqual(imported.mediaAssets); expect(redone.mediaAssets).toEqual([]); expect(state.history.undo.at(-1)).toMatchObject({ after: { mediaAssets: [] }, before: { mediaAssets: imported.mediaAssets }, label: "Reset controls", }); expect( isToolcraftControlsResetHistoryPatch(state.history.undo.at(-1)), ).toBe(true); }); it("restores predefined fileDrop media on global and section reset", () => { const app = defineToolcraft({ canvas: { enabled: true, upload: true }, media: { defaultAssets: [ { dataUrl: "data:image/png;base64,AAAA", fileName: "default-background.png", id: "default-background", layerId: "default-background-layer", mimeType: "image/png", size: { height: 1080, unit: "px", width: 1920 }, sourceTarget: "media.background", }, ], }, panels: { controls: { sections: [ { controls: { background: { defaultValue: null, target: "media.background", type: "fileDrop", }, }, title: "Background", }, ], title: "Controls", }, }, }); const initial = createToolcraftState(app); const deleted = toolcraftReducer(initial, { mediaId: "default-background", type: "media.delete", }); const sectionReset = toolcraftReducer(deleted, { label: "Reset Background section", targets: ["media.background"], type: "controls.resetTargets", }); const deletedAgain = toolcraftReducer(sectionReset, { mediaId: "default-background", type: "media.delete", }); const globalReset = toolcraftReducer(deletedAgain, { type: "controls.reset" }); expect(initial.mediaAssets.map((asset) => asset.id)).toEqual(["default-background"]); expect(deleted.mediaAssets).toEqual([]); expect(sectionReset.mediaAssets.map((asset) => asset.id)).toEqual([ "default-background", ]); expect(sectionReset.layers.map((layer) => layer.id)).toEqual([ "default-background-layer", ]); expect(sectionReset.selectedLayerId).toBe("default-background-layer"); expect(globalReset.mediaAssets.map((asset) => asset.id)).toEqual([ "default-background", ]); }); it("stores arbitrary fileDrop media without image dimensions and clears it on reset", () => { const app = defineToolcraft({ canvas: { enabled: true, upload: true }, panels: { controls: { sections: [ { controls: { source: { assetKind: "file", defaultValue: null, target: "files.source", type: "fileDrop", }, }, title: "Files", }, ], title: "Controls", }, }, }); const imported = toolcraftReducer(createToolcraftState(app), { asset: fileMediaAsset({ sourceTarget: "files.source" }), type: "media.import", }); const state = toolcraftReducer(imported, { type: "controls.reset" }); expect(imported.mediaAssets).toHaveLength(1); expect(imported.mediaAssets[0]).toMatchObject({ assetKind: "file", fileName: "notes.txt", sourceTarget: "files.source", }); expect( imported.mediaAssets[0]?.assetKind === "image" ? imported.mediaAssets[0].size : undefined, ).toBeUndefined(); expect(imported.canvas.size).toEqual(createToolcraftState(app).canvas.size); expect(state.mediaAssets).toEqual([]); }); it("clears only selected fileDrop media on section reset", () => { const app = defineToolcraft({ canvas: { enabled: true, upload: true }, panels: { controls: { sections: [ { controls: { primary: { defaultValue: null, target: "media.primary", type: "fileDrop", }, secondary: { defaultValue: null, target: "media.secondary", type: "fileDrop", }, }, title: "Sources", }, ], title: "Controls", }, }, }); const first = importImageMedia( createToolcraftState(app), { dataUrl: "data:image/png;base64,primary", fileName: "primary.png", sourceTarget: "media.primary", }, { replaceExisting: false }, ); const second = importImageMedia( first, { dataUrl: "data:image/png;base64,secondary", fileName: "secondary.png", sourceTarget: "media.secondary", }, { replaceExisting: false }, ); const state = toolcraftReducer(second, { label: "Reset Primary section", targets: ["media.primary"], type: "controls.resetTargets", }); expect(state.mediaAssets).toHaveLength(1); expect(state.mediaAssets[0]?.fileName).toBe("secondary.png"); expect(state.history.undo.at(-1)).toMatchObject({ after: { mediaAssets: state.mediaAssets }, before: { mediaAssets: second.mediaAssets }, label: "Reset Primary section", }); }); it("keeps layer-owned media on global reset and clears an explicitly reset source section", () => { const app = defineToolcraft({ canvas: { enabled: true, upload: true }, panels: { controls: { sections: [ { controls: { source: { defaultValue: null, target: "media.source", type: "fileDrop", }, }, title: "Source", }, ], title: "Controls", }, layers: true, }, }); const imported = toolcraftReducer(createToolcraftState(app), { asset: imageMediaAsset({ sourceTarget: "media.source" }), type: "media.import", }); const state = toolcraftReducer(imported, { type: "controls.reset" }); const sectionReset = toolcraftReducer(state, { label: "Reset Source section", targets: ["media.source"], type: "controls.resetTargets", }); expect(state.mediaAssets).toEqual(imported.mediaAssets); expect(sectionReset.mediaAssets).toEqual([]); expect(sectionReset.layers).toEqual([]); expect(sectionReset.selectedLayerId).toBeNull(); }); });