import { describe, expect, it } from 'vitest'; import { CreateAssetCommand, ResetAssetPropertyCommand, SetAssetPropertyCommand, } from '../../src/core/commands/assetCommands'; import { CreateContainerCommand } from '../../src/core/commands/containerCommands'; import { AddVariableCommand } from '../../src/core/commands/variableCommands'; import { ClearOverrideCommand, SetOverrideCommand, SetParentCommand, } from '../../src/core/commands/sceneObjectCommands'; import { instanceChildId } from '../../src/core/model/instance'; import { findAsset } from '../../src/core/model/Project'; import type { ContainerAsset } from '../../src/core/model/Asset'; import { assetDeviates, deviationMarks, objectDeviates } from '../../src/core/properties/deviation'; import { makeProject, makeSpriteScene, place } from '../helpers'; describe('deviation marks', () => { it('marks an object only once an override really deviates', () => { const f = makeSpriteScene(); const id = place(f, f.spriteId, { x: 0, y: 0 }); const deviates = () => objectDeviates(f.project, f.sceneOf(), f.object(id)); expect(deviates()).toBe(false); // The asset's own value carried as an override is no deviation. f.stack.execute(new SetOverrideCommand(f.sceneId, id, 'width', 100)); expect(deviates()).toBe(false); f.stack.execute(new SetOverrideCommand(f.sceneId, id, 'width', 250)); expect(deviates()).toBe(true); f.stack.execute(new ClearOverrideCommand(f.sceneId, id, 'width')); expect(deviates()).toBe(false); }); it('marks the ancestors of a deviating object, so a folded row still shows it', () => { const f = makeSpriteScene(); const parent = place(f, f.spriteId, { x: 0, y: 0 }); const child = place(f, f.spriteId, { x: 0, y: 0 }); f.stack.execute(new SetParentCommand(f.sceneId, child, parent)); expect(deviationMarks(f.project, f.sceneOf()).size).toBe(0); f.stack.execute(new SetOverrideCommand(f.sceneId, child, 'width', 250)); expect([...deviationMarks(f.project, f.sceneOf())].sort()).toEqual([child, parent].sort()); }); it('marks container content against its template, and the instance above it', () => { const f = makeSpriteScene(); const a = place(f, f.spriteId, { x: 0, y: 0 }); const create = new CreateContainerCommand(f.sceneId, [a]); f.stack.execute(create); const template = (findAsset(f.project, create.assetId) as ContainerAsset).objects[0]!.id; const content = instanceChildId(create.objectId, template); expect(deviationMarks(f.project, f.sceneOf()).size).toBe(0); f.stack.execute(new SetOverrideCommand(f.sceneId, content, 'width', 250)); expect([...deviationMarks(f.project, f.sceneOf())].sort()).toEqual([content, create.objectId].sort()); }); }); describe('asset deviation', () => { const makeAsset = (type: 'sprite' | 'behavior', name: string) => { const f = makeProject(); const create = new CreateAssetCommand(type, name); f.stack.execute(create); const asset = () => findAsset(f.project, create.asset.id)!; expect(asset().type).toBe(type); return { ...f, asset, assetId: create.asset.id }; }; it('marks an asset only once a property really differs from its default', () => { const f = makeAsset('sprite', 'Box'); expect(assetDeviates(f.project, f.asset())).toBe(false); // Written, but the default value – the inspector shows no gold, so neither does the list. f.stack.execute(new SetAssetPropertyCommand(f.assetId, 'width', 100)); expect(f.asset().props.width).toBe(100); expect(assetDeviates(f.project, f.asset())).toBe(false); f.stack.execute(new SetAssetPropertyCommand(f.assetId, 'width', 250)); expect(assetDeviates(f.project, f.asset())).toBe(true); f.stack.execute(new ResetAssetPropertyCommand(f.assetId, 'width')); expect(assetDeviates(f.project, f.asset())).toBe(false); }); it('leaves a behavior unmarked for its variables, which the inspector does not mark either', () => { const f = makeAsset('behavior', 'Mover'); f.stack.execute(new AddVariableCommand(f.assetId, 'speed', 'number')); f.stack.execute(new SetAssetPropertyCommand(f.assetId, 'speed', 42)); expect(f.asset().props.speed).toBe(42); expect(assetDeviates(f.project, f.asset())).toBe(false); f.stack.execute(new SetAssetPropertyCommand(f.assetId, 'enabled', false)); expect(assetDeviates(f.project, f.asset())).toBe(true); }); });