From 6ab81f6164d8cc8cd8ddfd3075cf6808e0227fdb Mon Sep 17 00:00:00 2001 From: Victor Giers Date: Tue, 31 Mar 2026 06:19:46 +0200 Subject: [PATCH] Add runtime interaction system tests --- .../domain/runtime-interaction-system.test.ts | 191 ++++++++++++++++++ 1 file changed, 191 insertions(+) create mode 100644 tests/domain/runtime-interaction-system.test.ts diff --git a/tests/domain/runtime-interaction-system.test.ts b/tests/domain/runtime-interaction-system.test.ts new file mode 100644 index 00000000..7a395a7b --- /dev/null +++ b/tests/domain/runtime-interaction-system.test.ts @@ -0,0 +1,191 @@ +import { describe, expect, it } from "vitest"; + +import { createTeleportPlayerInteractionLink, createToggleVisibilityInteractionLink } from "../../src/interactions/interaction-links"; +import { RuntimeInteractionSystem } from "../../src/runtime-three/runtime-interaction-system"; +import type { RuntimeSceneDefinition } from "../../src/runtime-three/runtime-scene-build"; + +function createRuntimeSceneFixture(): RuntimeSceneDefinition { + return { + world: { + background: { + mode: "solid", + colorHex: "#000000" + }, + ambientLight: { + colorHex: "#ffffff", + intensity: 1 + }, + sunLight: { + colorHex: "#ffffff", + intensity: 1, + direction: { + x: 0, + y: 1, + z: 0 + } + } + }, + brushes: [], + colliders: [], + sceneBounds: null, + entities: { + playerStarts: [], + soundEmitters: [], + triggerVolumes: [ + { + entityId: "entity-trigger-main", + position: { + x: 0, + y: 0, + z: 0 + }, + size: { + x: 2, + y: 2, + z: 2 + }, + triggerOnEnter: true, + triggerOnExit: true + } + ], + teleportTargets: [ + { + entityId: "entity-teleport-main", + position: { + x: 8, + y: 0, + z: -4 + }, + yawDegrees: 180 + } + ], + interactables: [] + }, + interactionLinks: [], + playerStart: null, + spawn: { + source: "fallback", + entityId: null, + position: { + x: 0, + y: 0, + z: 0 + }, + yawDegrees: 0 + } + }; +} + +describe("RuntimeInteractionSystem", () => { + it("dispatches teleport player on Trigger Volume enter", () => { + const runtimeScene = createRuntimeSceneFixture(); + runtimeScene.interactionLinks = [ + createTeleportPlayerInteractionLink({ + id: "link-teleport", + sourceEntityId: "entity-trigger-main", + trigger: "enter", + targetEntityId: "entity-teleport-main" + }) + ]; + + const interactionSystem = new RuntimeInteractionSystem(); + const dispatches: string[] = []; + + interactionSystem.updatePlayerPosition( + { + x: 0, + y: 0, + z: 0 + }, + runtimeScene, + { + teleportPlayer: (target, link) => { + dispatches.push(`${link.id}:${target.entityId}:${target.position.x}`); + }, + toggleBrushVisibility: () => { + dispatches.push("toggle"); + } + } + ); + interactionSystem.updatePlayerPosition( + { + x: 0.25, + y: 0, + z: 0.25 + }, + runtimeScene, + { + teleportPlayer: (target, link) => { + dispatches.push(`${link.id}:${target.entityId}:${target.position.x}`); + }, + toggleBrushVisibility: () => { + dispatches.push("toggle"); + } + } + ); + + expect(dispatches).toEqual(["link-teleport:entity-teleport-main:8"]); + }); + + it("dispatches visibility actions only when exiting an occupied Trigger Volume", () => { + const runtimeScene = createRuntimeSceneFixture(); + runtimeScene.interactionLinks = [ + createToggleVisibilityInteractionLink({ + id: "link-hide-door", + sourceEntityId: "entity-trigger-main", + trigger: "exit", + targetBrushId: "brush-door", + visible: false + }) + ]; + + const interactionSystem = new RuntimeInteractionSystem(); + const dispatches: Array<{ brushId: string; visible: boolean | undefined }> = []; + + interactionSystem.updatePlayerPosition( + { + x: 0, + y: 0, + z: 0 + }, + runtimeScene, + { + teleportPlayer: () => { + throw new Error("Teleport should not dispatch in this fixture."); + }, + toggleBrushVisibility: (brushId, visible) => { + dispatches.push({ + brushId, + visible + }); + } + } + ); + interactionSystem.updatePlayerPosition( + { + x: 3, + y: 0, + z: 0 + }, + runtimeScene, + { + teleportPlayer: () => { + throw new Error("Teleport should not dispatch in this fixture."); + }, + toggleBrushVisibility: (brushId, visible) => { + dispatches.push({ + brushId, + visible + }); + } + } + ); + + expect(dispatches).toEqual([ + { + brushId: "brush-door", + visible: false + } + ]); + }); +});