1import { RunId } from "@t3tools/contracts";
2import { describe, expect, it } from "vite-plus/test";
3import { deriveMessagesTimelineRows, liveWorkEntryLabel } from "./MessagesTimeline.logic";
4
5describe("long active tool groups", () => {
6 it.each([false, true])(
7 "preserves chronological order and the latest activity, expanded=%s",
8 (expanded) => {
9 const runId = RunId.make("long-active-run");
10 const createdAt = "2026-10-12T00:00:00Z";
11 const timelineEntries = Array.from({ length: 1_000 }, (_, index) => ({
12 id: `work-entry-${index}`,
13 kind: "work" as const,
14 createdAt,
15 entry: {
16 id: `work-${index}`,
17 createdAt,
18 runId,
19 label: `Tool ${index}`,
20 tone: index % 2 === 0 ? ("thinking" as const) : ("tool" as const),
21 itemType: index % 2 === 0 ? ("reasoning" as const) : ("command_execution" as const),
22 ...(index % 2 === 0 ? { detail: `Thought ${index}` } : {}),
23 toolLifecycleStatus: index === 999 ? ("inProgress" as const) : ("completed" as const),
24 },
25 }));
26 const rows = deriveMessagesTimelineRows({
27 timelineEntries,
28 isWorking: true,
29 runningRunId: runId,
30 activeTurnStartedAt: createdAt,
31 turnDiffSummaries: [],
32 supportsConversationRollback: false,
33 expandedWorkGroupIds: new Set(expanded ? ["work-group:work-entry-0"] : []),
34 });
35 const live = rows.find((row) => row.kind === "work-live");
36 expect(live).toBeDefined();
37 expect(live?.entry.id).toBe("work-999");
38 expect(live && liveWorkEntryLabel(live.entry, undefined, live.active)).toContain("999");
39 expect(live?.thought?.id).toBe("work-998");
40 expect(live?.groupedEntries.map(({ id }) => id)).toEqual(
41 timelineEntries.map(({ entry }) => entry.id),
42 );
43 expect(live?.groupId).toBe("work-group:work-entry-0");
44 const details = rows.filter((row) => row.kind === "work");
45 expect(details).toHaveLength(expanded ? 1 : 0);
46 if (expanded) {
47 expect(details[0]?.groupedEntries).toEqual(live?.groupedEntries);
48 }
49 },
50 );
51});