返回 DeepSeek-Reasonix
history-load-failure-contract.test.ts
根目录 / desktop / frontend / src / __tests__ / history-load-failure-contract.test.ts
1 // Run: npx tsx src/__tests__/history-load-failure-contract.test.ts
2 import assert from "node:assert/strict";
3 import { readFileSync } from "node:fs";
4 import { dirname, join } from "node:path";
5 import { fileURLToPath } from "node:url";
6 import { fetchPreparedHistorySlice } from "../lib/transcriptHistoryFetch";
7 import type { HistorySlice } from "../lib/types";
8
9 const root = join(dirname(fileURLToPath(import.meta.url)), "..");
10 const controller = readFileSync(join(root, "lib/useController.ts"), "utf8");
11 const store = readFileSync(join(root, "lib/transcriptStore.ts"), "utf8");
12 const chatPane = readFileSync(join(root, "app-shell/ChatPaneRegion.tsx"), "utf8");
13 const appView = readFileSync(join(root, "app-shell/AppRuntimeView.tsx"), "utf8");
14
15 assert.match(controller, /deferResetUntilHistory \?\? true/, "history reset waits for successful load");
16 assert.match(controller, /type: "hydrate_error"/, "history failure dispatches hydrate_error");
17 assert.match(controller, /applyHydrateErrorState|hydratePlaceholderItems/, "hydrate_error keeps previous content");
18 assert.match(readFileSync(join(root, "lib/hydrateErrorState.ts"), "utf8"), /keptItems/, "hydrateErrorState preserves items");
19 assert.match(controller, /throw new Error\(t\("history\.failedLoadHistory"\)\)/, "listSessions does not swallow failures as empty");
20 assert.match(controller, /retrySessionHistory/, "retry path is exported");
21 assert.match(controller, /startTranscriptFollow/, "retry establishes an authoritative Follow snapshot");
22 assert.match(
23 controller,
24 /loadSessionDataForTab\(tabId, false, "startup", \{ preserveCachedHistory: true \}\)/,
25 "failed clear keeps the visible transcript instead of a resident snapshot",
26 );
27 assert.match(store, /fetchPreparedHistorySlice/, "transcript store uses the shared history reader");
28 await assert.rejects(
29 fetchPreparedHistorySlice(async () => ({ entries: [], error: " history unavailable " }) as unknown as HistorySlice, () => true),
30 { message: "history unavailable" },
31 "history reader rejects slice errors instead of treating them as empty history",
32 );
33 assert.match(appView, /retrySessionHistory/, "App wires history retry control");
34 assert.match(chatPane, /SessionRecoveryBanner/, "App surfaces persistent history recovery above the transcript");
35
36 console.log(" PASS history load failure contract");
37
37 lines TYPESCRIPT