Update dialogue tests to use NPC entities

This commit is contained in:
2026-04-15 09:57:42 +02:00
parent 35b9b33d65
commit 9cbe4dfbfa

View File

@@ -37,7 +37,6 @@ import {
} from "../../src/entities/entity-instances"; } from "../../src/entities/entity-instances";
import { import {
createControlInteractionLink, createControlInteractionLink,
createStartDialogueInteractionLink,
type InteractionLink type InteractionLink
} from "../../src/interactions/interaction-links"; } from "../../src/interactions/interaction-links";
import { createProjectScheduleRoutine } from "../../src/scheduler/project-scheduler"; import { createProjectScheduleRoutine } from "../../src/scheduler/project-scheduler";
@@ -317,7 +316,7 @@ describe("RuntimeHost", () => {
host.dispose(); host.dispose();
}); });
it("opens, advances, and closes project dialogues through the runtime host", () => { it("opens, advances, and closes NPC dialogues through the runtime host", () => {
vi.spyOn(console, "warn").mockImplementation(() => undefined); vi.spyOn(console, "warn").mockImplementation(() => undefined);
vi.spyOn(RapierCollisionWorld, "create").mockResolvedValue({ vi.spyOn(RapierCollisionWorld, "create").mockResolvedValue({
dispose: vi.fn(), dispose: vi.fn(),
@@ -326,12 +325,11 @@ describe("RuntimeHost", () => {
) )
} as unknown as RapierCollisionWorld); } as unknown as RapierCollisionWorld);
const triggerVolume = createTriggerVolumeEntity({
id: "entity-trigger-main"
});
const document = createEmptySceneDocument(); const document = createEmptySceneDocument();
document.entities[triggerVolume.id] = triggerVolume; const npc = createNpcEntity({
document.dialogues.dialogues["dialogue-warning"] = { id: "entity-npc-operator",
dialogues: [
{
id: "dialogue-warning", id: "dialogue-warning",
title: "Generator Warning", title: "Generator Warning",
lines: [ lines: [
@@ -346,14 +344,11 @@ describe("RuntimeHost", () => {
text: "A low hum fills the room." text: "A low hum fills the room."
} }
] ]
}; }
document.interactionLinks["link-start-dialogue"] = ],
createStartDialogueInteractionLink({ defaultDialogueId: "dialogue-warning"
id: "link-start-dialogue",
sourceEntityId: triggerVolume.id,
trigger: "enter",
dialogueId: "dialogue-warning"
}); });
document.entities[npc.id] = npc;
const runtimeScene = buildRuntimeSceneFromDocument(document); const runtimeScene = buildRuntimeSceneFromDocument(document);
const host = new RuntimeHost({ const host = new RuntimeHost({
@@ -367,8 +362,9 @@ describe("RuntimeHost", () => {
const hostInternals = host as unknown as { const hostInternals = host as unknown as {
createInteractionDispatcher(): { createInteractionDispatcher(): {
startDialogue( startNpcDialogue(
dialogueId: string, npcEntityId: string,
dialogueId: string | null,
source?: { source?: {
kind: "interactionLink" | "npc" | "direct"; kind: "interactionLink" | "npc" | "direct";
sourceEntityId: string | null; sourceEntityId: string | null;
@@ -379,13 +375,12 @@ describe("RuntimeHost", () => {
}; };
}; };
const dispatcher = hostInternals.createInteractionDispatcher(); const dispatcher = hostInternals.createInteractionDispatcher();
const dialogueLink = document.interactionLinks["link-start-dialogue"]!;
dispatcher.startDialogue("dialogue-warning", { dispatcher.startNpcDialogue(npc.id, "dialogue-warning", {
kind: "interactionLink", kind: "npc",
sourceEntityId: dialogueLink.sourceEntityId, sourceEntityId: npc.id,
linkId: dialogueLink.id, linkId: null,
trigger: "enter" trigger: "click"
}); });
host.advanceRuntimeDialogue(); host.advanceRuntimeDialogue();
host.advanceRuntimeDialogue(); host.advanceRuntimeDialogue();
@@ -393,26 +388,28 @@ describe("RuntimeHost", () => {
expect(dialogueStates).toEqual([ expect(dialogueStates).toEqual([
expect.objectContaining({ expect.objectContaining({
dialogueId: "dialogue-warning", dialogueId: "dialogue-warning",
npcEntityId: npc.id,
lineIndex: 0, lineIndex: 0,
speakerName: "Operator", speakerName: "Operator",
text: "The generator is unstable.", text: "The generator is unstable.",
source: { source: {
kind: "interactionLink", kind: "npc",
sourceEntityId: triggerVolume.id, sourceEntityId: npc.id,
linkId: dialogueLink.id, linkId: null,
trigger: "enter" trigger: "click"
} }
}), }),
expect.objectContaining({ expect.objectContaining({
dialogueId: "dialogue-warning", dialogueId: "dialogue-warning",
npcEntityId: npc.id,
lineIndex: 1, lineIndex: 1,
speakerName: null, speakerName: null,
text: "A low hum fills the room.", text: "A low hum fills the room.",
source: { source: {
kind: "interactionLink", kind: "npc",
sourceEntityId: triggerVolume.id, sourceEntityId: npc.id,
linkId: dialogueLink.id, linkId: null,
trigger: "enter" trigger: "click"
} }
}), }),
null null
@@ -421,7 +418,7 @@ describe("RuntimeHost", () => {
host.dispose(); host.dispose();
}); });
it("publishes late dialogue handlers, ignores repeated same-dialogue starts, and replaces with a different dialogue", () => { it("publishes late dialogue handlers, ignores repeated same-NPC dialogue starts, and replaces with a different NPC dialogue", () => {
vi.spyOn(console, "warn").mockImplementation(() => undefined); vi.spyOn(console, "warn").mockImplementation(() => undefined);
vi.spyOn(RapierCollisionWorld, "create").mockResolvedValue({ vi.spyOn(RapierCollisionWorld, "create").mockResolvedValue({
dispose: vi.fn(), dispose: vi.fn(),
@@ -431,7 +428,10 @@ describe("RuntimeHost", () => {
} as unknown as RapierCollisionWorld); } as unknown as RapierCollisionWorld);
const document = createEmptySceneDocument(); const document = createEmptySceneDocument();
document.dialogues.dialogues["dialogue-a"] = { const npcA = createNpcEntity({
id: "entity-npc-a",
dialogues: [
{
id: "dialogue-a", id: "dialogue-a",
title: "A", title: "A",
lines: [ lines: [
@@ -441,8 +441,14 @@ describe("RuntimeHost", () => {
text: "First dialogue." text: "First dialogue."
} }
] ]
}; }
document.dialogues.dialogues["dialogue-b"] = { ],
defaultDialogueId: "dialogue-a"
});
const npcB = createNpcEntity({
id: "entity-npc-b",
dialogues: [
{
id: "dialogue-b", id: "dialogue-b",
title: "B", title: "B",
lines: [ lines: [
@@ -452,7 +458,12 @@ describe("RuntimeHost", () => {
text: "Second dialogue." text: "Second dialogue."
} }
] ]
}; }
],
defaultDialogueId: "dialogue-b"
});
document.entities[npcA.id] = npcA;
document.entities[npcB.id] = npcB;
const host = new RuntimeHost({ const host = new RuntimeHost({
enableRendering: false enableRendering: false
@@ -461,8 +472,9 @@ describe("RuntimeHost", () => {
const hostInternals = host as unknown as { const hostInternals = host as unknown as {
createInteractionDispatcher(): { createInteractionDispatcher(): {
startDialogue( startNpcDialogue(
dialogueId: string, npcEntityId: string,
dialogueId: string | null,
source?: { source?: {
kind: "interactionLink" | "npc" | "direct"; kind: "interactionLink" | "npc" | "direct";
sourceEntityId: string | null; sourceEntityId: string | null;
@@ -474,11 +486,11 @@ describe("RuntimeHost", () => {
}; };
const dispatcher = hostInternals.createInteractionDispatcher(); const dispatcher = hostInternals.createInteractionDispatcher();
dispatcher.startDialogue("dialogue-a", { dispatcher.startNpcDialogue(npcA.id, "dialogue-a", {
kind: "interactionLink", kind: "npc",
sourceEntityId: "entity-trigger-a", sourceEntityId: npcA.id,
linkId: "link-dialogue-a", linkId: null,
trigger: "enter" trigger: "click"
}); });
const dialogueStates: Array<RuntimeDialogueState | null> = []; const dialogueStates: Array<RuntimeDialogueState | null> = [];
@@ -486,15 +498,15 @@ describe("RuntimeHost", () => {
dialogueStates.push(dialogue); dialogueStates.push(dialogue);
}); });
dispatcher.startDialogue("dialogue-a", { dispatcher.startNpcDialogue(npcA.id, "dialogue-a", {
kind: "interactionLink",
sourceEntityId: "entity-trigger-a",
linkId: "link-dialogue-a",
trigger: "enter"
});
dispatcher.startDialogue("dialogue-b", {
kind: "npc", kind: "npc",
sourceEntityId: "entity-npc-merchant", sourceEntityId: npcA.id,
linkId: null,
trigger: "click"
});
dispatcher.startNpcDialogue(npcB.id, "dialogue-b", {
kind: "npc",
sourceEntityId: npcB.id,
linkId: null, linkId: null,
trigger: "click" trigger: "click"
}); });
@@ -502,20 +514,22 @@ describe("RuntimeHost", () => {
expect(dialogueStates).toEqual([ expect(dialogueStates).toEqual([
expect.objectContaining({ expect.objectContaining({
dialogueId: "dialogue-a", dialogueId: "dialogue-a",
npcEntityId: npcA.id,
text: "First dialogue.", text: "First dialogue.",
source: { source: {
kind: "interactionLink", kind: "npc",
sourceEntityId: "entity-trigger-a", sourceEntityId: npcA.id,
linkId: "link-dialogue-a", linkId: null,
trigger: "enter" trigger: "click"
} }
}), }),
expect.objectContaining({ expect.objectContaining({
dialogueId: "dialogue-b", dialogueId: "dialogue-b",
npcEntityId: npcB.id,
text: "Second dialogue.", text: "Second dialogue.",
source: { source: {
kind: "npc", kind: "npc",
sourceEntityId: "entity-npc-merchant", sourceEntityId: npcB.id,
linkId: null, linkId: null,
trigger: "click" trigger: "click"
} }