1import { renderToStaticMarkup } from "react-dom/server";
2import { describe, expect, it, vi } from "vite-plus/test";
3
4const state = vi.hoisted(() => ({
5 projection: null as unknown,
6 workflow: null as unknown,
7}));
8
9vi.mock("@t3tools/client-runtime/environment", () => ({
10 scopeThreadRef: () => ({}) as never,
11}));
12
13vi.mock("@t3tools/client-runtime/state/thread-workflows", () => ({
14 deriveThreadQueueWorkflowState: () => state.workflow,
15}));
16
17vi.mock("../../state/entities", () => ({
18 useThreadProjection: () => state.projection,
19}));
20
21vi.mock("../../state/threads", () => ({
22 threadEnvironment: {
23 cancelQueuedRun: Symbol("cancelQueuedRun"),
24 promoteQueuedRun: Symbol("promoteQueuedRun"),
25 reorderQueuedRun: Symbol("reorderQueuedRun"),
26 },
27}));
28
29vi.mock("../../state/use-atom-command", () => ({
30 useAtomCommand: () => async () => undefined,
31}));
32
33vi.mock("../../assets/assetUrls", () => ({
34 useAssetUrls: (_environmentId: never, resources: ReadonlyArray<{ attachmentId: string }>) =>
35 resources.map((resource) => `https://assets.test/${resource.attachmentId}`),
36}));
37
38import { QueuedRunsControl } from "./QueuedRunsControl";
39
40describe("QueuedRunsControl automatic completion delivery", () => {
41 it("does not render a queue control when only hidden delivery remains", () => {
42 state.projection = {
43 projection: {
44 messages: [
45 {
46 delegatedCompletion: {
47 parentRunId: "run:parent",
48 generation: 1,
49 taskIds: ["task:child"],
50 },
51 id: "message:completion",
52 },
53 ],
54 },
55 };
56 state.workflow = {
57 activeRun: { id: "run:active" },
58 canPromoteToSteer: true,
59 canReorder: true,
60 queuedRuns: [],
61 };
62
63 const html = renderToStaticMarkup(
64 <QueuedRunsControl
65 environmentId={"environment:test" as never}
66 optimisticMessages={[]}
67 threadId={"thread:test" as never}
68 editingRunId={null}
69 onEditQueuedRun={() => undefined}
70 onCancelEdit={() => undefined}
71 />,
72 );
73
74 expect(html).toBe("");
75 });
76});
77
78describe("QueuedRunsControl attachments and edit mode", () => {
79 const workflowWithAttachment = () => ({
80 activeRun: { id: "run:active" },
81 canPromoteToSteer: true,
82 canReorder: true,
83 queuedRuns: [
84 {
85 run: { id: "run:queued", userMessageId: "message:queued" },
86 text: "Queued with a screenshot",
87 attachments: [
88 {
89 type: "image",
90 id: "attachment-1",
91 name: "screenshot.png",
92 mimeType: "image/png",
93 sizeBytes: 128,
94 },
95 ],
96 },
97 ],
98 });
99
100 it("renders an attachment thumbnail on the queued row", () => {
101 state.projection = { projection: { messages: [] } };
102 state.workflow = workflowWithAttachment();
103
104 const html = renderToStaticMarkup(
105 <QueuedRunsControl
106 environmentId={"environment:test" as never}
107 optimisticMessages={[]}
108 threadId={"thread:test" as never}
109 editingRunId={null}
110 onEditQueuedRun={() => undefined}
111 onCancelEdit={() => undefined}
112 />,
113 );
114
115 expect(html).toContain("https://assets.test/attachment-1");
116 expect(html).toContain("Queued with a screenshot");
117 expect(html).toContain("Edit queued message");
118 expect(html).toContain("Reorder queued message");
119 expect(html).not.toContain("Move queued message up");
120 });
121
122 it("drops the optimistic pending row once the projection holds its message", () => {
123 state.projection = {
124 projection: { messages: [{ id: "message:acknowledged", text: "hello" }] },
125 };
126 state.workflow = {
127 activeRun: { id: "run:active" },
128 canPromoteToSteer: true,
129 canReorder: true,
130 queuedRuns: [],
131 };
132
133 const html = renderToStaticMarkup(
134 <QueuedRunsControl
135 environmentId={"environment:test" as never}
136 optimisticMessages={[
137 {
138 id: "message:acknowledged" as never,
139 inputIntent: "queued_turn",
140 text: "hello",
141 attachments: [],
142 },
143 ]}
144 threadId={"thread:test" as never}
145 editingRunId={null}
146 onEditQueuedRun={() => undefined}
147 onCancelEdit={() => undefined}
148 />,
149 );
150
151 expect(html).toBe("");
152 });
153
154 it("keeps the original queued message visible while editing", () => {
155 state.projection = { projection: { messages: [] } };
156 state.workflow = workflowWithAttachment();
157
158 const html = renderToStaticMarkup(
159 <QueuedRunsControl
160 environmentId={"environment:test" as never}
161 optimisticMessages={[]}
162 threadId={"thread:test" as never}
163 editingRunId={"run:queued" as never}
164 onEditQueuedRun={() => undefined}
165 onCancelEdit={() => undefined}
166 />,
167 );
168
169 expect(html).toContain("Queued with a screenshot");
170 });
171});