返回 DeepSeek-Reasonix
session-catalog-status-ownership.test.ts
根目录 / desktop / frontend / src / __tests__ / session-catalog-status-ownership.test.ts
1 import assert from "node:assert/strict";
2 import { readFileSync } from "node:fs";
3
4 let generation = 0;
5 const statusWriteIsAllowed = (candidateGeneration: number, rebuildFailed: boolean) => !rebuildFailed && candidateGeneration === generation;
6 const renderedStates: string[] = [];
7 let resolveRemoteStatus: ((state: string) => void) | undefined;
8 const remoteStatus = new Promise<string>((resolve) => {
9 resolveRemoteStatus = resolve;
10 });
11 const remoteGeneration = generation;
12 const lateRemoteWrite = remoteStatus.then((state) => {
13 if (statusWriteIsAllowed(remoteGeneration, false)) renderedStates.push(state);
14 });
15
16 // The desktop rebuild rejects after the finished event has already started its
17 // status read. Restoring the retryable failure must fence out that late read.
18 generation += 1;
19 renderedStates.push("degraded");
20 resolveRemoteStatus?.("opening");
21 await lateRemoteWrite;
22 assert.deepEqual(
23 renderedStates,
24 ["degraded"],
25 "a late pre-failure status response cannot replace the restored retry state",
26 );
27
28 const postFailureGeneration = generation;
29 if (statusWriteIsAllowed(postFailureGeneration, true)) renderedStates.push("opening");
30 assert.deepEqual(
31 renderedStates,
32 ["degraded"],
33 "status reads started after a failed rebuild cannot replace its retry state during watcher startup",
34 );
35
36 const retryGeneration = generation;
37 if (statusWriteIsAllowed(retryGeneration, false)) renderedStates.push("ready");
38 assert.deepEqual(renderedStates, ["degraded", "ready"], "a new rebuild re-enables authoritative status writes");
39
40 const projectTreeSource = readFileSync(new URL("../components/ProjectTree.tsx", import.meta.url), "utf8");
41 assert.match(
42 projectTreeSource,
43 /catch \{\s*catalogRebuildFailedRef\.current = true; catalogStatusGenerationRef\.current \+= 1; setCatalogStatus\(catalogStatus\)/,
44 "ProjectTree invalidates older status reads before restoring a failed rebuild",
45 );
46 assert.match(
47 projectTreeSource,
48 /GetSessionCatalogStatus\(\)[\s\S]*!catalogRebuildFailedRef\.current && catalogStatusGeneration === catalogStatusGenerationRef\.current/,
49 "ProjectTree fences every event-driven status write behind rebuild ownership",
50 );
51 assert.match(
52 projectTreeSource,
53 /GetProjectTreeSnapshot\(\)[\s\S]*!catalogRebuildFailedRef\.current && catalogStatusGeneration === catalogStatusGenerationRef\.current/,
54 "ProjectTree fences snapshot status writes behind the same rebuild ownership",
55 );
56
57 console.log("session catalog status ownership tests passed");
58
58 lines TYPESCRIPT