|
1 | 1 | import { describe, expect, it } from "vitest"; |
2 | | -import { markerAfterActiveChat, markerAfterActivity } from "./thinking-marker"; |
| 2 | +import { markerAfterActiveChat, markerAfterActivity, markerChatId } from "./thinking-marker"; |
| 3 | +import { TOOL_PENDING_DEADLINE_MS } from "./turn-deadlines"; |
3 | 4 |
|
4 | 5 | describe("thinking marker", () => { |
5 | 6 | it("marks the chat that is working and clears it when the turn settles", () => { |
6 | | - const working = markerAfterActivity(null, "chat_1", "working"); |
7 | | - expect(working).toBe("chat_1"); |
8 | | - expect(markerAfterActivity(working, "chat_1", null)).toBe(null); |
| 7 | + const working = markerAfterActivity(null, "chat_1", "working", 0); |
| 8 | + expect(markerChatId(working, "chat_1", 0)).toBe("chat_1"); |
| 9 | + expect(markerAfterActivity(working, "chat_1", null, 0)).toBe(null); |
9 | 10 | }); |
10 | 11 |
|
11 | 12 | it("ignores a settled report from another chat", () => { |
12 | | - expect(markerAfterActivity("chat_1", "chat_2", null)).toBe("chat_1"); |
| 13 | + const working = markerAfterActivity(null, "chat_1", "working", 0); |
| 14 | + const other = markerAfterActivity(working, "chat_2", null, 0); |
| 15 | + expect(markerChatId(other, "chat_2", 0)).toBe("chat_1"); |
13 | 16 | }); |
14 | 17 |
|
15 | | - it("clears the marker when the user switches away mid-turn", () => { |
16 | | - // The streaming chat unmounts without reporting null, so only the switch clears it. |
17 | | - expect(markerAfterActiveChat("chat_1", "chat_2")).toBe(null); |
18 | | - expect(markerAfterActiveChat("chat_1", undefined)).toBe(null); |
| 18 | + it("keeps the marker when the chat closes mid-turn", () => { |
| 19 | + const working = markerAfterActivity(null, "chat_1", "working", 0); |
| 20 | + const closed = markerAfterActiveChat(working, undefined, 1_000); |
| 21 | + expect(markerChatId(closed, undefined, 1_000)).toBe("chat_1"); |
| 22 | + expect(markerChatId(markerAfterActiveChat(working, "chat_2", 1_000), "chat_2", 1_000)).toBe( |
| 23 | + "chat_1" |
| 24 | + ); |
19 | 25 | }); |
20 | 26 |
|
21 | | - it("keeps the marker the chat just reported for itself", () => { |
22 | | - expect(markerAfterActiveChat("chat_1", "chat_1")).toBe("chat_1"); |
| 27 | + it("expires a closed marker once activity reports stop", () => { |
| 28 | + const working = markerAfterActivity(null, "chat_1", "working", 0); |
| 29 | + const closed = markerAfterActiveChat(working, undefined, 1_000); |
| 30 | + expect(markerChatId(closed, undefined, 1_000 + TOOL_PENDING_DEADLINE_MS)).toBe(null); |
| 31 | + }); |
| 32 | + |
| 33 | + it("does not expire the marker while its chat is open", () => { |
| 34 | + const working = markerAfterActivity(null, "chat_1", "working", 0); |
| 35 | + expect(markerChatId(working, "chat_1", TOOL_PENDING_DEADLINE_MS * 10)).toBe("chat_1"); |
| 36 | + }); |
| 37 | + |
| 38 | + it("clears the marker when the chat is reopened and already settled", () => { |
| 39 | + const working = markerAfterActivity(null, "chat_1", "working", 0); |
| 40 | + const reopened = markerAfterActiveChat(working, "chat_1", 1_000); |
| 41 | + expect(markerAfterActivity(reopened, "chat_1", null, 1_000)).toBe(null); |
| 42 | + }); |
| 43 | + |
| 44 | + it("extends the marker when the reopened chat is still streaming", () => { |
| 45 | + const working = markerAfterActivity(null, "chat_1", "working", 0); |
| 46 | + const closed = markerAfterActiveChat(working, undefined, 1_000); |
| 47 | + const streaming = markerAfterActivity(closed, "chat_1", "working", 5_000); |
| 48 | + expect(markerChatId(streaming, undefined, 1_000 + TOOL_PENDING_DEADLINE_MS)).toBe("chat_1"); |
23 | 49 | }); |
24 | 50 | }); |
0 commit comments