返回 DeepSeek-Reasonix
delivery-continue-commands.test.tsx
根目录 / desktop / frontend / src / __tests__ / delivery-continue-commands.test.tsx
1 import assert from "node:assert/strict";
2 import React, { act } from "react";
3 import { createRoot } from "react-dom/client";
4 import { JSDOM } from "jsdom";
5 import { useDeliveryContinueCommands } from "../app-runtime/useDeliveryContinueCommands";
6 import { createSessionSurfaceFence } from "../app-runtime/sessionTarget";
7 import type { Translator } from "../lib/i18n";
8
9 const dom = new JSDOM("<div id='root'></div>");
10 Object.assign(globalThis, { window: dom.window, document: dom.window.document, IS_REACT_ACT_ENVIRONMENT: true });
11 const root = createRoot(document.getElementById("root")!);
12
13 const t = ((key: string) => key) as Translator;
14
15 function deferred<T>() {
16 let resolve!: (value: T) => void;
17 const promise = new Promise<T>((yes) => { resolve = yes; });
18 return { promise, resolve };
19 }
20
21 const calls: string[] = [];
22 let resumeGate: ReturnType<typeof deferred<boolean>> | null = null;
23 let resumeResult = true;
24 const fence = createSessionSurfaceFence();
25
26 let states!: ReturnType<typeof useDeliveryContinueCommands>;
27 function Probe({ ready = true, goal }: { ready?: boolean; goal?: string }) {
28 states = useDeliveryContinueCommands({
29 surfaceFence: fence,
30 ready,
31 goal,
32 t,
33 ports: {
34 resumeGoal: async (tabId) => {
35 calls.push(`resume:${tabId}`);
36 if (resumeGate) return resumeGate.promise;
37 return resumeResult;
38 },
39 recoverDelivery: async (tabId, prompt) => { calls.push(`send:${tabId}:${prompt}`); },
40 },
41 });
42 return null;
43 }
44 const paint = (props?: { ready?: boolean; goal?: string }) => act(async () => root.render(<Probe {...props} />));
45
46 try {
47 await paint();
48 fence.commit("A", "A:1");
49
50 await paint({ ready: false });
51 await act(async () => { await states.handleDeliveryContinue(); });
52 assert.deepEqual(calls, [], "a controller that is not ready continues nothing");
53
54 await paint({ ready: true });
55 await act(async () => { await states.handleDeliveryContinue(); });
56 assert.deepEqual(calls, ["send:A:notice.deliveryIncompleteContinuePrompt"],
57 "a goal-less delivery sends the recovery prompt to the committed tab");
58 calls.length = 0;
59
60 await paint({ goal: "ship it" });
61 await act(async () => { await states.handleDeliveryContinue(); });
62 assert.deepEqual(calls, ["resume:A", "send:A:notice.deliveryIncompleteContinuePrompt"],
63 "a goal tab resumes its goal before the recovery send");
64 calls.length = 0;
65
66 resumeResult = false;
67 await act(async () => { await states.handleDeliveryContinue(); });
68 assert.deepEqual(calls, ["resume:A"], "a goal that refuses to resume is not poked further");
69 resumeResult = true;
70
71 resumeGate = deferred<boolean>();
72 calls.length = 0;
73 let stale: Promise<void> | undefined;
74 await act(async () => { stale = states.handleDeliveryContinue(); });
75 fence.commit("B", "B:1");
76 await act(async () => {
77 resumeGate!.resolve(true);
78 await stale;
79 });
80 assert.deepEqual(calls, ["resume:A"], "a mid-flight tab switch revokes the captured ownership and blocks the send");
81 resumeGate = null;
82 fence.commit("A", "A:1");
83 calls.length = 0;
84 await act(async () => { await states.handleDeliveryContinue(); });
85 assert.deepEqual(calls, ["resume:A", "send:A:notice.deliveryIncompleteContinuePrompt"],
86 "a fresh capture on the restored tab owns the UI again");
87
88 fence.dispose();
89 calls.length = 0;
90 await act(async () => { await states.handleDeliveryContinue(); });
91 assert.deepEqual(calls, [], "without a committed surface there is no continuation target");
92
93 console.log("delivery continue commands: ready gate, goal resume chain, stale-ownership fence and empty-target gate passed");
94 } finally { dom.window.close(); }
95
95 lines Plain Text