The inspector already marked an asset value that differs from its schema default, but the Assets panel gave no hint, so a changed asset looked like an untouched one until you opened it. The rule sits next to the existing objectDeviates as a pure function: assetDeviates asks whether any marked property differs, markedAssetSchema says which rows the inspector marks at all. buildAssetSection now builds its rows from that same list, replacing the behavior/rest split it used to carry, so the list cannot claim a deviation the inspector then fails to show. A behavior's variables are deliberately not in it. Their default is declared on the variable itself, which means the asset value *is* that default; counting them would paint the fixture's Mover gold while the inspector beside it marks nothing.
91 lines
4.3 KiB
TypeScript
91 lines
4.3 KiB
TypeScript
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.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.asset())).toBe(false);
|
||
f.stack.execute(new SetAssetPropertyCommand(f.assetId, 'width', 250));
|
||
expect(assetDeviates(f.asset())).toBe(true);
|
||
f.stack.execute(new ResetAssetPropertyCommand(f.assetId, 'width'));
|
||
expect(assetDeviates(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.asset())).toBe(false);
|
||
f.stack.execute(new SetAssetPropertyCommand(f.assetId, 'enabled', false));
|
||
expect(assetDeviates(f.asset())).toBe(true);
|
||
});
|
||
});
|