import { describe, expect, test } from "bun:test"; import { createInitialAppState } from "@editor/initial-state"; import type { AppState } from "@editor/state"; import { createAppStateSelectorSnapshot, shallowEqual } from "./useAppState"; describe("app state selector snapshot", () => { test("reuses selected snapshots when equality reports no relevant changes", () => { const state = createInitialAppState("Test"); const snapshot = createAppStateSelectorSnapshot(selectShellLikeState, shallowEqual); const selected = snapshot.getSnapshot(state); const previewOnlyUpdate: AppState = { ...state, editor: { ...state.editor, brushStrokePreview: { layerId: "layer", assetId: "asset", source: "preview" }, }, }; expect(snapshot.updateSnapshot(previewOnlyUpdate)).toBe(false); expect(snapshot.getSnapshot(previewOnlyUpdate)).toBe(selected); }); test("can collapse brush preview updates to presence instead of position", () => { const state = createInitialAppState("Test"); const snapshot = createAppStateSelectorSnapshot((next: AppState) => ({ hasBrushPreview: Boolean(next.editor.brushPreview) }), shallowEqual); const withoutPreview = snapshot.getSnapshot(state); const withPreview: AppState = { ...state, editor: { ...state.editor, brushPreview: { position: { x: 10, y: 20 } }, }, }; expect(snapshot.updateSnapshot(withPreview)).toBe(true); const previewPresent = snapshot.getSnapshot(withPreview); expect(previewPresent).not.toBe(withoutPreview); expect(previewPresent.hasBrushPreview).toBe(true); const movedPreview: AppState = { ...withPreview, editor: { ...withPreview.editor, brushPreview: { position: { x: 30, y: 40 } }, }, }; expect(snapshot.updateSnapshot(movedPreview)).toBe(false); expect(snapshot.getSnapshot(movedPreview)).toBe(previewPresent); }); test("shallow equality uses object keys and Object.is value checks", () => { expect(shallowEqual({ id: "a", value: Number.NaN }, { id: "a", value: Number.NaN })).toBe(true); expect(shallowEqual({ id: "a", value: 0 }, { id: "a", value: -0 })).toBe(false); expect(shallowEqual({ id: "a" }, { id: "a", extra: true })).toBe(false); }); }); function selectShellLikeState(state: AppState) { return { document: state.document, selection: state.editor.selection, viewport: state.editor.viewport, tools: state.editor.tools, transformSession: state.editor.transformSession, maskEdit: state.editor.maskEdit, }; }