返回 DeepSeek-Reasonix
ask-submit.test.ts
根目录 / desktop / frontend / src / __tests__ / ask-submit.test.ts
1 // Run: tsx src/__tests__/ask-submit.test.ts
2
3 import type { AppBindings } from "../lib/bridge";
4 import { answerPromptForActiveTurn } from "../lib/inboxSubmit";
5 import type { QuestionAnswer } from "../lib/types";
6
7 let passed = 0;
8 let failed = 0;
9
10 function eq(actual: unknown, expected: unknown, label: string) {
11 if (actual === expected) {
12 process.stdout.write(` PASS ${label}\n`);
13 passed += 1;
14 } else {
15 process.stdout.write(` FAIL ${label}: expected ${JSON.stringify(expected)}, got ${JSON.stringify(actual)}\n`);
16 failed += 1;
17 }
18 }
19
20 function binding(overrides: Partial<AppBindings>): AppBindings {
21 return overrides as AppBindings;
22 }
23
24 const answers: QuestionAnswer[] = [{ questionId: "q1", selected: ["yes"] }];
25 console.log("\nAsk prompt exact-request submission");
26
27 {
28 let pendingCalls = 0;
29 const exactCalls: string[] = [];
30 await answerPromptForActiveTurn(binding({
31 PendingPromptIdentitiesForTab: async () => { pendingCalls += 1; return []; },
32 ResolvePromptForTab: async (tabId, promptId, turnId) => { exactCalls.push(`${tabId}:${turnId}:${promptId}`); },
33 }), "tab-ask", "ask-1", answers, "turn-known");
34 eq(pendingCalls, 0, "complete Ask identity does not query the current turn");
35 eq(exactCalls.join("|"), "tab-ask:turn-known:ask-1", "the card's original turn fences the exact answer");
36 }
37
38 {
39 let pendingCalls = 0;
40 const exactCalls: string[] = [];
41 await answerPromptForActiveTurn(binding({
42 PendingPromptIdentitiesForTab: async () => { pendingCalls += 1; return [{ promptId: "ask-2", turnId: "turn-original", runtimeEpoch: "runtime-a", kind: "ask" }]; },
43 ResolvePromptForTab: async (tabId, promptId, turnId) => { exactCalls.push(`${tabId}:${turnId}:${promptId}`); },
44 }), "tab-ask", "ask-2", answers);
45 eq(pendingCalls, 1, "missing local identity queries pending prompts once");
46 eq(exactCalls.join("|"), "tab-ask:turn-original:ask-2", "only the matching pending Ask can complete identity");
47 }
48
49 {
50 let exactCalls = 0;
51 let rejected = "";
52 try {
53 await answerPromptForActiveTurn(binding({
54 PendingPromptIdentitiesForTab: async () => [],
55 ResolvePromptForTab: async () => { exactCalls += 1; },
56 }), "tab-ask", "ask-3", answers);
57 } catch (error) {
58 rejected = error instanceof Error ? error.message : String(error);
59 }
60 eq(rejected.includes("stale") || rejected.includes("exact identity"), true, "missing exact prompt identity rejects visibly");
61 eq(exactCalls, 0, "missing turn id never calls the exact endpoint with an empty fence");
62 }
63
64 {
65 let exactCalls = 0;
66 let rejected = "";
67 try {
68 await answerPromptForActiveTurn(binding({
69 PendingPromptIdentitiesForTab: async () => { throw new Error("pending lookup failed"); },
70 ResolvePromptForTab: async () => { exactCalls += 1; },
71 }), "tab-ask", "ask-rpc", answers);
72 } catch (error) {
73 rejected = error instanceof Error ? error.message : String(error);
74 }
75 eq(rejected, "pending lookup failed", "pending identity lookup failure propagates");
76 eq(exactCalls, 0, "failed turn lookup never calls the exact endpoint");
77 }
78
79 {
80 let rejected = "";
81 try {
82 await answerPromptForActiveTurn(binding({
83 ResolvePromptForTab: async () => { throw new Error("stale turn"); },
84 }), "tab-ask", "ask-4", answers, "turn-original", "runtime-a");
85 } catch (error) {
86 rejected = error instanceof Error ? error.message : String(error);
87 }
88 eq(rejected, "stale turn", "exact endpoint rejection propagates to the decision surface");
89 }
90
91 {
92 let rejected = "";
93 try {
94 await answerPromptForActiveTurn(binding({}), "tab-ask", "ask-legacy", answers, "turn-original", "runtime-a");
95 } catch (error) {
96 rejected = error instanceof Error ? error.message : String(error);
97 }
98 eq(rejected.includes("upgrade the host"), true, "missing exact prompt API fails closed");
99 }
100
101 console.log(`\n${passed} passed, ${failed} failed, ${passed + failed} total`);
102 if (failed > 0) process.exit(1);
103
103 lines TYPESCRIPT