返回 DeepSeek-Reasonix
recovery-quiet-notifications.test.ts
根目录 / desktop / frontend / src / __tests__ / recovery-quiet-notifications.test.ts
1 // Run: tsx src/__tests__/recovery-quiet-notifications.test.ts
2 //
3 // Recovery copies remain protected by the backend. Covered/adopted lifecycle
4 // noise stays quiet; only catalog-confirmed unique divergence gets one toast.
5
6 import { readFileSync } from "node:fs";
7 import { dirname, resolve } from "node:path";
8 import { fileURLToPath } from "node:url";
9
10 import { en } from "../locales/en";
11 import { zh } from "../locales/zh";
12 import { zhTW } from "../locales/zh-TW";
13
14 let passed = 0;
15 let failed = 0;
16
17 function ok(cond: boolean, label: string) {
18 if (cond) {
19 process.stdout.write(` PASS ${label}\n`);
20 passed += 1;
21 } else {
22 process.stdout.write(` FAIL ${label}\n`);
23 failed += 1;
24 }
25 }
26
27 const here = dirname(fileURLToPath(import.meta.url));
28 const appSource = readFileSync(resolve(here, "../App.tsx"), "utf8");
29 const recoveryHostSource = readFileSync(resolve(here, "../components/SessionRecoveryVersionsHost.tsx"), "utf8");
30 const recoveryRuntimeSource = readFileSync(resolve(here, "../lib/sessionRecoveryRuntime.ts"), "utf8");
31 const noticesSource = readFileSync(resolve(here, "../lib/controllerNotices.ts"), "utf8");
32
33 console.log("\nquiet recovery notifications and confirmed divergence");
34
35 ok(!appSource.includes("banner--recovery"), "App does not render a recovery banner");
36 ok(!appSource.includes('t("recovery.noticeSavedCopy")'), "App does not toast when a physical recovery copy is merely created");
37 ok(recoveryHostSource.includes("recovery.divergedToast"), "App has a dedicated confirmed-divergence toast");
38 ok(recoveryRuntimeSource.includes("onProjectTreeChangedV2"), "divergence is rechecked after catalog revisions");
39 ok(recoveryHostSource.includes("onSessionRecoveryFailed"), "recovery failures are surfaced by the recovery host");
40 ok(!appSource.includes("AcknowledgeTabRecovery"), "App does not expose recovery acknowledgement controls");
41 ok(!appSource.includes("OpenTabRecoveryParent"), "App does not expose recovery compare controls");
42 ok(!appSource.includes("recovery.openOriginalFailed"), "App does not carry recovery compare failure text");
43
44 ok(noticesSource.includes("function quietTranscriptNoticeKey"), "controller centralizes quiet transcript notices");
45 ok(noticesSource.includes("if (quietTranscriptNoticeKey(rawText, code))"), "raw quiet notices are skipped before localization");
46 ok(noticesSource.includes("if (quietTranscriptNoticeKey(text, code))"), "localized quiet notices are skipped before rendering");
47
48 const removedPromptKeys = [
49 "recovery.open",
50 "recovery.toast",
51 "recovery.failedLease",
52 "recovery.failedUnavailable",
53 "recovery.banner",
54 "recovery.bannerCompare",
55 "recovery.bannerDismiss",
56 "recovery.openOriginalFailed",
57 ];
58 for (const [name, dict] of [["en", en], ["zh", zh], ["zh-TW", zhTW]] as const) {
59 for (const key of removedPromptKeys) {
60 ok(!(key in dict), `${name} locale omits ${key}`);
61 }
62 }
63
64 console.log(`\n${passed} passed, ${failed} failed`);
65 if (failed > 0) process.exit(1);
66
66 lines TYPESCRIPT