diff --git a/tests/stages/page_chase.test.ts b/tests/stages/page_chase.test.ts index 1e8e577..545d414 100644 --- a/tests/stages/page_chase.test.ts +++ b/tests/stages/page_chase.test.ts @@ -498,4 +498,72 @@ describe("chase stage skeleton", () => { ).length; expect(highlightCount).toBe(expectedMoves); }); + + it("destroys old move highlights across refresh when available moves change", () => { + const stateA = { + turn: 0, + winCount: 0, + snapshot: { + seed: 500, + status: "playing", + thiefNodeId: "A", + guardNodeId: "D", + exitNodeId: "E", + graph: { + nodes: { + A: { id: "A", q: 0, r: 0, neighbors: ["B", "C"] }, + B: { id: "B", q: 1, r: 0, neighbors: ["A"] }, + C: { id: "C", q: 0, r: 1, neighbors: ["A"] }, + D: { id: "D", q: -1, r: 0, neighbors: [] }, + E: { id: "E", q: 2, r: 0, neighbors: [] }, + }, + edgeList: [ + ["A", "B"], + ["A", "C"], + ], + }, + }, + }; + const stateB = { + ...stateA, + turn: 1, + snapshot: { + ...stateA.snapshot, + thiefNodeId: "C", + guardNodeId: "B", + graph: { + ...stateA.snapshot.graph, + nodes: { + ...stateA.snapshot.graph.nodes, + C: { ...stateA.snapshot.graph.nodes.C, neighbors: ["A", "E"] }, + }, + }, + }, + }; + + const getState = vi.fn().mockReturnValueOnce(stateA).mockReturnValueOnce(stateB); + const scene = new ChaseScene({ + model: { + getState, + moveThief: vi.fn(), + newRound: vi.fn(), + retryRound: vi.fn(), + } as any, + }); + void (scene as any).onSceneLayout(); + + const firstHighlights = (scene as any).graphLayer.children.filter( + (c: any) => c.label === "move-highlight", + ); + expect(firstHighlights.length).toBe(2); + + scene.refreshView(); + const secondHighlights = (scene as any).graphLayer.children.filter( + (c: any) => c.label === "move-highlight", + ); + expect(secondHighlights.length).toBe(2); + expect(secondHighlights[0]).not.toBe(firstHighlights[0]); + expect((firstHighlights[0] as any).destroyed).toBe(true); + expect((firstHighlights[1] as any).destroyed).toBe(true); + }); });