Files
webeditor3d/tests/unit/entity-instances.test.ts

228 lines
7.3 KiB
TypeScript

import { describe, expect, it } from "vitest";
import {
DEFAULT_CAMERA_RIG_DEFAULT_ACTIVE,
DEFAULT_CAMERA_RIG_LOOK_AROUND_ENABLED,
DEFAULT_CAMERA_RIG_LOOK_AROUND_PITCH_LIMIT_DEGREES,
DEFAULT_CAMERA_RIG_LOOK_AROUND_RECENTER_SPEED,
DEFAULT_CAMERA_RIG_LOOK_AROUND_YAW_LIMIT_DEGREES,
DEFAULT_CAMERA_RIG_PRIORITY,
DEFAULT_CAMERA_RIG_TARGET_OFFSET,
DEFAULT_CAMERA_RIG_TRANSITION_DURATION_SECONDS,
DEFAULT_CAMERA_RIG_TRANSITION_MODE,
DEFAULT_POINT_LIGHT_COLOR_HEX,
DEFAULT_POINT_LIGHT_DISTANCE,
DEFAULT_POINT_LIGHT_INTENSITY,
DEFAULT_PLAYER_START_BOX_SIZE,
DEFAULT_PLAYER_START_CAPSULE_HEIGHT,
DEFAULT_PLAYER_START_CAPSULE_RADIUS,
DEFAULT_PLAYER_START_CROUCH_SETTINGS,
DEFAULT_PLAYER_START_EYE_HEIGHT,
DEFAULT_PLAYER_START_ALLOW_LOOK_INPUT_TARGET_SWITCH,
DEFAULT_PLAYER_START_INTERACTION_ANGLE_DEGREES,
DEFAULT_PLAYER_START_INTERACTION_REACH_METERS,
DEFAULT_PLAYER_START_JUMP_SETTINGS,
DEFAULT_PLAYER_START_MOVE_SPEED,
DEFAULT_PLAYER_START_MOVEMENT_CAPABILITIES,
DEFAULT_PLAYER_START_SPRINT_SETTINGS,
DEFAULT_PLAYER_START_TARGET_BUTTON_CYCLES_ACTIVE_TARGET,
DEFAULT_SPOT_LIGHT_ANGLE_DEGREES,
DEFAULT_SPOT_LIGHT_COLOR_HEX,
DEFAULT_SPOT_LIGHT_DISTANCE,
DEFAULT_SPOT_LIGHT_DIRECTION,
DEFAULT_SPOT_LIGHT_INTENSITY,
DEFAULT_INTERACTABLE_PROMPT,
DEFAULT_NPC_YAW_DEGREES,
DEFAULT_SOUND_EMITTER_AUDIO_ASSET_ID,
DEFAULT_SOUND_EMITTER_MAX_DISTANCE,
DEFAULT_SOUND_EMITTER_REF_DISTANCE,
DEFAULT_SOUND_EMITTER_VOLUME,
DEFAULT_TRIGGER_VOLUME_SIZE,
createPointLightEntity,
createDefaultEntityInstance,
createInteractableEntity,
createNpcEntity,
createSpotLightEntity,
getEntityRegistryEntry
} from "../../src/entities/entity-instances";
describe("entity registry defaults", () => {
it("creates explicit typed defaults for each supported entity kind", () => {
expect(createDefaultEntityInstance("playerStart")).toMatchObject({
kind: "playerStart",
position: { x: 0, y: 0, z: 0 },
yawDegrees: 0,
navigationMode: "firstPerson",
interactionReachMeters: DEFAULT_PLAYER_START_INTERACTION_REACH_METERS,
interactionAngleDegrees: DEFAULT_PLAYER_START_INTERACTION_ANGLE_DEGREES,
allowLookInputTargetSwitch:
DEFAULT_PLAYER_START_ALLOW_LOOK_INPUT_TARGET_SWITCH,
targetButtonCyclesActiveTarget:
DEFAULT_PLAYER_START_TARGET_BUTTON_CYCLES_ACTIVE_TARGET,
movementTemplate: {
kind: "default",
moveSpeed: DEFAULT_PLAYER_START_MOVE_SPEED,
capabilities: DEFAULT_PLAYER_START_MOVEMENT_CAPABILITIES,
jump: DEFAULT_PLAYER_START_JUMP_SETTINGS,
sprint: DEFAULT_PLAYER_START_SPRINT_SETTINGS,
crouch: DEFAULT_PLAYER_START_CROUCH_SETTINGS
},
collider: {
mode: "capsule",
eyeHeight: DEFAULT_PLAYER_START_EYE_HEIGHT,
capsuleRadius: DEFAULT_PLAYER_START_CAPSULE_RADIUS,
capsuleHeight: DEFAULT_PLAYER_START_CAPSULE_HEIGHT,
boxSize: DEFAULT_PLAYER_START_BOX_SIZE
},
inputBindings: {
keyboard: {
moveForward: "KeyW",
moveBackward: "KeyS",
moveLeft: "KeyA",
moveRight: "KeyD",
jump: "Space",
sprint: "ShiftLeft",
crouch: "ControlLeft",
interact: "MouseLeft",
clearTarget: "KeyQ",
pauseTime: "KeyP"
},
gamepad: {
moveForward: "leftStickUp",
moveBackward: "leftStickDown",
moveLeft: "leftStickLeft",
moveRight: "leftStickRight",
jump: "buttonSouth",
sprint: "leftStickPress",
crouch: "buttonEast",
interact: "buttonWest",
clearTarget: "buttonNorth",
pauseTime: "buttonMenu",
cameraLook: "rightStick"
}
}
});
expect(createDefaultEntityInstance("pointLight")).toMatchObject({
kind: "pointLight",
position: { x: 0, y: 0, z: 0 },
colorHex: DEFAULT_POINT_LIGHT_COLOR_HEX,
intensity: DEFAULT_POINT_LIGHT_INTENSITY,
distance: DEFAULT_POINT_LIGHT_DISTANCE
});
expect(createDefaultEntityInstance("cameraRig")).toMatchObject({
kind: "cameraRig",
position: { x: 0, y: 0, z: 0 },
rigType: "fixed",
priority: DEFAULT_CAMERA_RIG_PRIORITY,
defaultActive: DEFAULT_CAMERA_RIG_DEFAULT_ACTIVE,
target: {
kind: "player"
},
targetOffset: DEFAULT_CAMERA_RIG_TARGET_OFFSET,
transitionMode: DEFAULT_CAMERA_RIG_TRANSITION_MODE,
transitionDurationSeconds: DEFAULT_CAMERA_RIG_TRANSITION_DURATION_SECONDS,
lookAround: {
enabled: DEFAULT_CAMERA_RIG_LOOK_AROUND_ENABLED,
yawLimitDegrees: DEFAULT_CAMERA_RIG_LOOK_AROUND_YAW_LIMIT_DEGREES,
pitchLimitDegrees: DEFAULT_CAMERA_RIG_LOOK_AROUND_PITCH_LIMIT_DEGREES,
recenterSpeed: DEFAULT_CAMERA_RIG_LOOK_AROUND_RECENTER_SPEED
}
});
expect(createDefaultEntityInstance("spotLight")).toMatchObject({
kind: "spotLight",
position: { x: 0, y: 0, z: 0 },
direction: DEFAULT_SPOT_LIGHT_DIRECTION,
colorHex: DEFAULT_SPOT_LIGHT_COLOR_HEX,
intensity: DEFAULT_SPOT_LIGHT_INTENSITY,
distance: DEFAULT_SPOT_LIGHT_DISTANCE,
angleDegrees: DEFAULT_SPOT_LIGHT_ANGLE_DEGREES
});
expect(createDefaultEntityInstance("soundEmitter")).toMatchObject({
kind: "soundEmitter",
position: { x: 0, y: 0, z: 0 },
audioAssetId: DEFAULT_SOUND_EMITTER_AUDIO_ASSET_ID,
volume: DEFAULT_SOUND_EMITTER_VOLUME,
refDistance: DEFAULT_SOUND_EMITTER_REF_DISTANCE,
maxDistance: DEFAULT_SOUND_EMITTER_MAX_DISTANCE,
autoplay: false,
loop: false
});
expect(createDefaultEntityInstance("triggerVolume")).toMatchObject({
kind: "triggerVolume",
position: { x: 0, y: 0, z: 0 },
size: DEFAULT_TRIGGER_VOLUME_SIZE,
triggerOnEnter: true,
triggerOnExit: false
});
expect(createDefaultEntityInstance("teleportTarget")).toMatchObject({
kind: "teleportTarget",
position: { x: 0, y: 0, z: 0 },
yawDegrees: 0
});
expect(createDefaultEntityInstance("npc")).toMatchObject({
kind: "npc",
position: { x: 0, y: 0, z: 0 },
yawDegrees: DEFAULT_NPC_YAW_DEGREES,
modelAssetId: null
});
expect(createDefaultEntityInstance("interactable")).toMatchObject({
kind: "interactable",
position: { x: 0, y: 0, z: 0 },
radius: 1.5,
prompt: DEFAULT_INTERACTABLE_PROMPT,
enabled: true
});
});
it("keeps entity metadata and prompt validation explicit", () => {
expect(getEntityRegistryEntry("triggerVolume")).toMatchObject({
kind: "triggerVolume",
label: "Trigger Volume"
});
expect(
createInteractableEntity({
prompt: " Open "
}).prompt
).toBe("Open");
expect(() =>
createInteractableEntity({
prompt: " "
})
).toThrow("Interactable prompt must be non-empty.");
expect(() =>
createPointLightEntity({
distance: 0
})
).toThrow(
"Point Light distance must be a finite number greater than zero."
);
expect(() =>
createSpotLightEntity({
direction: {
x: 0,
y: 0,
z: 0
}
})
).toThrow("Spot Light direction must not be the zero vector.");
expect(() =>
createNpcEntity({
actorId: " "
})
).toThrow("NPC actorId must be a non-empty string.");
});
});