From 6b4071a63dacd28e8fd8b57a2022ee6036044ea1 Mon Sep 17 00:00:00 2001 From: Victor Giers Date: Tue, 14 Apr 2026 01:38:13 +0200 Subject: [PATCH] Add test for control interaction link serialization --- .../control-interaction-links.test.ts | 109 ++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 tests/serialization/control-interaction-links.test.ts diff --git a/tests/serialization/control-interaction-links.test.ts b/tests/serialization/control-interaction-links.test.ts new file mode 100644 index 00000000..cfc0884a --- /dev/null +++ b/tests/serialization/control-interaction-links.test.ts @@ -0,0 +1,109 @@ +import { describe, expect, it } from "vitest"; + +import { + createLightControlTargetRef, + createSetLightEnabledControlEffect +} from "../../src/controls/control-surface"; +import { createEmptySceneDocument, NPC_PRESENCE_SCENE_DOCUMENT_VERSION, SCENE_DOCUMENT_VERSION } from "../../src/document/scene-document"; +import { migrateSceneDocument } from "../../src/document/migrate-scene-document"; +import { + createPointLightEntity, + createSoundEmitterEntity, + createTriggerVolumeEntity +} from "../../src/entities/entity-instances"; +import { + createControlInteractionLink, + createPlaySoundInteractionLink +} from "../../src/interactions/interaction-links"; +import { + createProjectAssetStorageKey, + type AudioAssetRecord +} from "../../src/assets/project-assets"; +import { + parseSceneDocumentJson, + serializeSceneDocument +} from "../../src/serialization/scene-document-json"; + +describe("control interaction link serialization", () => { + it("round-trips authored control interaction links", () => { + const triggerVolume = createTriggerVolumeEntity({ + id: "entity-trigger-main" + }); + const pointLight = createPointLightEntity({ + id: "entity-point-light-main" + }); + const document = { + ...createEmptySceneDocument(), + entities: { + [triggerVolume.id]: triggerVolume, + [pointLight.id]: pointLight + }, + interactionLinks: { + "link-light-off": createControlInteractionLink({ + id: "link-light-off", + sourceEntityId: triggerVolume.id, + trigger: "enter", + effect: createSetLightEnabledControlEffect({ + target: createLightControlTargetRef("pointLight", pointLight.id), + enabled: false + }) + }) + } + }; + + expect(parseSceneDocumentJson(serializeSceneDocument(document))).toEqual( + document + ); + }); + + it("migrates v44 documents without changing existing interaction links", () => { + const audioAsset = { + id: "asset-audio-main", + kind: "audio" as const, + sourceName: "loop.ogg", + mimeType: "audio/ogg", + storageKey: createProjectAssetStorageKey("asset-audio-main"), + byteLength: 1024, + metadata: { + kind: "audio" as const, + durationSeconds: 3, + channelCount: 2, + sampleRateHz: 48000, + warnings: [] + } + } satisfies AudioAssetRecord; + const triggerVolume = createTriggerVolumeEntity({ + id: "entity-trigger-main" + }); + const soundEmitter = createSoundEmitterEntity({ + id: "entity-sound-main", + audioAssetId: audioAsset.id + }); + const legacyDocument = { + ...createEmptySceneDocument(), + version: NPC_PRESENCE_SCENE_DOCUMENT_VERSION, + assets: { + [audioAsset.id]: audioAsset + }, + entities: { + [triggerVolume.id]: triggerVolume, + [soundEmitter.id]: soundEmitter + }, + interactionLinks: { + "link-play-sound": createPlaySoundInteractionLink({ + id: "link-play-sound", + sourceEntityId: triggerVolume.id, + trigger: "enter", + targetSoundEmitterId: soundEmitter.id + }) + } + }; + + const migratedDocument = migrateSceneDocument(legacyDocument); + + expect(migratedDocument.version).toBe(SCENE_DOCUMENT_VERSION); + expect(migratedDocument.interactionLinks).toEqual( + legacyDocument.interactionLinks + ); + }); +});