feat: make demo story screen interactive

This commit is contained in:
Codex
2026-07-28 13:06:49 +08:00
parent ea209c9b69
commit 77b42a7879
6 changed files with 877 additions and 46 deletions
+39
View File
@@ -0,0 +1,39 @@
import { describe, expect, it } from "vitest";
import initialView from "../../fixtures/player-view/initial.json";
import type { PlayerView, TurnRequest } from "@contracts";
import { submitDemoTurn } from "./turnAdapter";
function request(intent: TurnRequest["intent"], input: string): TurnRequest {
return {
storyId: initialView.storyId,
branchId: initialView.branchId,
expectedNodeId: initialView.nodeId,
actionId: `test_${intent}`,
intent,
input
};
}
describe("local turn adapter", () => {
it("preserves literal player input without inventing additional player speech", async () => {
const literalInput = "我把手电筒放在长椅上。";
const result = await submitDemoTurn(
request("speak_or_act", literalInput),
initialView as PlayerView
);
const playerBeats = result.playerView.beats.filter((beat) => beat.speaker === "你");
expect(playerBeats).toHaveLength(1);
expect(playerBeats[0]?.text).toBe(literalInput);
});
it("accepts an empty Continue intent without creating a player beat", async () => {
const result = await submitDemoTurn(request("continue", ""), initialView as PlayerView);
expect(result.committedNodeId).toBe("node_002");
expect(result.playerView.beats.some((beat) => beat.speaker === "你")).toBe(false);
expect(result.playerView.beats.at(-1)?.speaker).toBe("娜娜");
});
});