/** * The undo contract every "write one key into a property bag" command shares: a key that was * not in the bag before the edit must be *absent* again afterwards, not present as undefined. * Serialization and the "is this an override?" checks in the inspector go by key presence. */ import { describe, expect, it } from 'vitest'; import { ResetAssetPropertyCommand, SetAssetPropertyCommand } from '../../src/core/commands/assetCommands'; import { SetNodeParamCommand } from '../../src/core/commands/graphCommands'; import { ClearOverrideCommand, SetOverrideCommand } from '../../src/core/commands/sceneObjectCommands'; import { findAsset } from '../../src/core/model/Project'; import { graphEditor, makeBehavior, makeSpriteScene, place } from '../helpers'; describe('bag value commands', () => { it('undoing an override leaves no key behind', () => { const fixture = makeSpriteScene(); const box = place(fixture, fixture.spriteId, { x: 0, y: 0 }); fixture.stack.execute(new SetOverrideCommand(fixture.sceneId, box, 'width', 33)); expect(fixture.object(box).overrides).toEqual({ width: 33 }); fixture.stack.undo(); expect('width' in fixture.object(box).overrides).toBe(false); }); it('undoing a cleared override puts the old value back', () => { const fixture = makeSpriteScene(); const box = place(fixture, fixture.spriteId, { x: 0, y: 0 }); fixture.stack.execute(new SetOverrideCommand(fixture.sceneId, box, 'width', 33)); fixture.stack.execute(new ClearOverrideCommand(fixture.sceneId, box, 'width')); expect('width' in fixture.object(box).overrides).toBe(false); fixture.stack.undo(); expect(fixture.object(box).overrides.width).toBe(33); }); it('coerces on set and restores the untouched default on undo of a reset', () => { const fixture = makeSpriteScene(); const sprite = () => findAsset(fixture.project, fixture.spriteId)!; // 'width' is a number property, so a numeric string is coerced. fixture.stack.execute(new SetAssetPropertyCommand(fixture.spriteId, 'width', '250')); expect(sprite().props.width).toBe(250); fixture.stack.execute(new ResetAssetPropertyCommand(fixture.spriteId, 'width')); expect(sprite().props.width).toBe(100); fixture.stack.undo(); expect(sprite().props.width).toBe(250); }); it('restores a node param that had no value before', () => { const fixture = makeSpriteScene(); const behavior = makeBehavior(fixture, 'B'); // `Owner` declares no params, so 'value' is an inline input value: stored as given. const node = graphEditor(fixture, behavior).addNode('Owner'); fixture.stack.execute(new SetNodeParamCommand(behavior.id, node.id, 'value', 7)); expect(node.params.value).toBe(7); fixture.stack.undo(); expect('value' in node.params).toBe(false); }); });