Tooling: - Prettier as the single formatting authority (110 columns, single quotes, measured against the existing style); Markdown excluded because table-cell padding turns the README glossary into 1000-character lines. - Type-aware ESLint ending in eslint-config-prettier, so a rule always means "this is a bug", never "this looks different". - .editorconfig and an `npm run check` that runs typecheck, lint, format and tests in one go. Findings fixed on the first run: three more duplicate imports, four String(unknown) calls (parameter types narrowed instead of casts), two dead initialisers, two redundant casts, a console.log for a real error. Two warnings were false here and are disabled with a reason in place. Tests 132 -> 269: - node-catalog.test.ts covers every node with a run(), with a guard that fails when a new node has no row. - behavior-events.test.ts covers the ten event nodes through a running World, checking timing rather than existence. - Input's state machine (press/release/releaseAll) is reachable without DOM events now; the DOM handlers are thin adapters. Compare fell back to == without a configured operator although the schema default is <; aligned. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
64 lines
2.2 KiB
TypeScript
64 lines
2.2 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
import { SetOverrideCommand } from '../../src/core/commands/sceneObjectCommands';
|
|
import { deserializeProject } from '../../src/core/store/serialize';
|
|
import { makeSpriteScene, place, roundTrip } from '../helpers';
|
|
|
|
describe('serialize', () => {
|
|
it('round-trips a project', () => {
|
|
const f = makeSpriteScene();
|
|
const box = place(f, f.spriteId, { x: 7, y: 8 });
|
|
f.stack.execute(new SetOverrideCommand(f.sceneId, box, 'width', 33));
|
|
expect(roundTrip(f.project)).toEqual(f.project);
|
|
});
|
|
|
|
it('repairs broken documents', () => {
|
|
const project = deserializeProject(
|
|
{
|
|
name: 'Broken',
|
|
activeSceneId: 'missing',
|
|
assets: [
|
|
{
|
|
id: 's1',
|
|
type: 'scene',
|
|
name: 'Scene',
|
|
props: { backgroundColor: '#000000', junk: 1 },
|
|
objects: [
|
|
{
|
|
id: 'o1',
|
|
assetId: 'sp1',
|
|
position: { x: '5', y: null },
|
|
overrides: { color: '#00ff00', width: -3, foo: 1 },
|
|
},
|
|
{ id: 'o2', assetId: 'nope', position: {} },
|
|
{ id: 'o3', assetId: 's1', position: {} },
|
|
],
|
|
},
|
|
{ id: 'sp1', type: 'sprite', props: { width: 10 } },
|
|
{ id: 'x', type: 'texture' },
|
|
{ type: 'camera' },
|
|
],
|
|
},
|
|
'fallback-id',
|
|
);
|
|
expect(project.id).toBe('fallback-id');
|
|
expect(project.activeSceneId).toBe('s1');
|
|
expect(project.assets.map((a) => a.id)).toEqual(['s1', 'sp1']);
|
|
const scene = project.assets[0]!;
|
|
expect(scene.type === 'scene' && scene.props).toEqual({ backgroundColor: 0 });
|
|
const objects = scene.type === 'scene' ? scene.objects : [];
|
|
expect(objects).toHaveLength(1);
|
|
expect(objects[0]).toEqual({
|
|
id: 'o1',
|
|
assetId: 'sp1',
|
|
name: '',
|
|
position: { x: 5, y: 0, z: 0 },
|
|
editorOffset: { x: 0, y: 0 },
|
|
overrides: { color: 0x00ff00, width: 1 },
|
|
parentId: '',
|
|
templateId: '',
|
|
});
|
|
expect(project.assets[1]!.name).toBe('sprite');
|
|
expect(project.assets[1]!.props).toEqual({ enabled: true, width: 10, height: 100, color: 0xe0553f });
|
|
});
|
|
});
|