返回 DeepSeek-Reasonix
frontend-diagnostics.test.ts
根目录 / desktop / frontend / src / __tests__ / frontend-diagnostics.test.ts
1 import assert from "node:assert/strict";
2 import {
3 analyzeFrontendDiagnosticAnomalies,
4 createFrontendDiagnostics,
5 isFrontendDiagnosticsBuild,
6 isSupportedFrontendDiagnosticSchemaVersion,
7 } from "../lib/frontendDiagnostics";
8
9 let now = 10_000;
10 const diagnostics = createFrontendDiagnostics({
11 maxEvents: 32,
12 now: () => now,
13 randomID: () => "0123456789abcdef0123456789abcdef",
14 environment: () => ({
15 buildCommit: "test-commit",
16 buildChannel: "canary",
17 platform: "windows",
18 userAgent: "Reasonix test",
19 devicePixelRatio: 1.25,
20 viewportWidth: 1440,
21 viewportHeight: 900,
22 language: "zh-CN",
23 reducedMotion: false,
24 }),
25 });
26
27 diagnostics.record("app", "app.surface", { tabId: "private-tab", transcriptText: "PRIVATE_TEXT" });
28 assert.equal(diagnostics.getSnapshot().eventCount, 0, "idle recorder ignores events");
29
30 diagnostics.start();
31 now += 10;
32 diagnostics.record("browser", "click", {
33 target: "button",
34 path: "C:\\Users\\private-user\\secret",
35 token: "PRIVATE_TOKEN",
36 text: "PRIVATE_TEXT",
37 });
38 now += 10;
39 diagnostics.record("transcript", "transcript.row-measure", {
40 rowIndex: 44,
41 rowKind: "answer",
42 layoutVersion: "1:42",
43 layoutVariant: "text-flow",
44 estimateSource: "static",
45 estimatedSize: 1_800,
46 measuredSize: 420,
47 sizeDelta: -1_380,
48 contentRevision: 3,
49 });
50 diagnostics.record("history", "history.items-patch", {
51 patchCount: 2,
52 contentRevision: 4,
53 });
54 diagnostics.record("transcript", "transcript.scroll-write", {
55 source: "recovery-end",
56 owner: "recovery",
57 writeKind: "scrollToIndex",
58 targetIndex: "LAST",
59 targetTop: 720,
60 previousMode: "manual",
61 canClaimTail: false,
62 tailCommand: true,
63 });
64 diagnostics.mark();
65 for (let index = 0; index < 40; index += 1) {
66 now += 1;
67 diagnostics.record("browser", "scroll", { scrollTop: index * 10, scrollHeight: 2_400, clientHeight: 800 });
68 }
69 diagnostics.record("transcript", "transcript.scroll-write", {
70 source: "recovery-end",
71 owner: "recovery",
72 writeKind: "scrollToIndex",
73 targetIndex: "LAST",
74 targetTop: 720,
75 });
76 diagnostics.record("transcript", "transcript.row-measure", {
77 layoutVersion: "1:42",
78 layoutVariant: "text-flow",
79 estimateSource: "static",
80 measuredSize: 420,
81 });
82 diagnostics.record("history", "history.items-patch", { patchCount: 2, contentRevision: 4 });
83 diagnostics.record("workspace", "workspace.session-directory", {
84 workspaceSessions: 7,
85 visibleSessions: 5,
86 hiddenSessions: 2,
87 hiddenByCollapsed: 1,
88 hiddenByTruncation: 1,
89 runtimeOnlySessions: 1,
90 recoveryCopies: 2,
91 changeReason: "recovery-copy",
92 workspaceRoot: "C:\\Users\\private-user\\workspace",
93 topicId: "private-topic-id",
94 label: "PRIVATE_TITLE",
95 });
96
97 const active = diagnostics.getSnapshot();
98 assert.equal(active.status, "recording");
99 assert.equal(active.eventCount, 32, "ring buffer remains bounded");
100 assert.ok(active.droppedEventCount > 0, "overflow is visible in the summary");
101 assert.equal(active.markerCount, 0, "evicted markers are not counted as retained");
102
103 const payload = diagnostics.stop();
104 assert.equal(payload.schemaVersion, 2);
105 assert.equal(isSupportedFrontendDiagnosticSchemaVersion(1), true, "schema v1 remains readable by replay tools");
106 assert.equal(isSupportedFrontendDiagnosticSchemaVersion(2), true, "schema v2 is the current capture format");
107 assert.equal(isSupportedFrontendDiagnosticSchemaVersion(3), false, "unknown future schemas are rejected explicitly");
108 assert.equal(payload.manifest.platform, "windows");
109 assert.equal(payload.events[payload.events.length - 1]?.type, "stop");
110 const serialized = JSON.stringify(payload);
111 assert.equal(serialized.includes("scrollToIndex"), true, "scroll writer details remain available for analysis");
112 assert.equal(serialized.includes("targetIndex"), true, "scroll target remains available for analysis");
113 assert.equal(serialized.includes("recovery-end"), true, "scroll transition source remains available for analysis");
114 assert.equal(serialized.includes("history.items-patch"), true, "history patch event remains available for analysis");
115 assert.equal(serialized.includes("layoutVersion"), true, "row layout version remains available for analysis");
116 assert.equal(serialized.includes("layoutVariant"), true, "row layout variant remains available for analysis");
117 assert.equal(serialized.includes("estimateSource"), true, "height estimate source remains available for analysis");
118 assert.equal(serialized.includes("workspace.session-directory"), true, "sidebar directory event remains available for analysis");
119 assert.equal(serialized.includes("workspaceSessions"), true, "sidebar session counts remain available for analysis");
120 assert.ok(Array.isArray(payload.summary.anomalies), "payload includes automatic anomaly analysis");
121 for (const forbidden of ["PRIVATE_TEXT", "PRIVATE_TOKEN", "private-user", "private-tab", "path", "token", "tabId"]) {
122 assert.equal(serialized.includes(forbidden), false, `payload excludes ${forbidden}`);
123 }
124
125 const frozenCount = diagnostics.getSnapshot().eventCount;
126 diagnostics.record("browser", "scroll", { scrollTop: 999 });
127 assert.equal(diagnostics.getSnapshot().eventCount, frozenCount, "stopped recorder remains frozen");
128
129 assert.equal(isFrontendDiagnosticsBuild("test", false), true);
130 assert.equal(isFrontendDiagnosticsBuild("canary", false), true);
131 assert.equal(isFrontendDiagnosticsBuild("preview", false), true);
132 assert.equal(isFrontendDiagnosticsBuild("stable", true), true);
133 assert.equal(isFrontendDiagnosticsBuild("stable", false), false);
134
135 assert.deepEqual(analyzeFrontendDiagnosticAnomalies([
136 { t: 0, type: "navigation.begin", intent: 7 },
137 { t: 1, type: "workspace.session-directory", workspaceSessions: 8 },
138 { t: 2, type: "workspace.session-directory", workspaceSessions: 7 },
139 { t: 3, type: "navigation.settle", intent: 7 },
140 { t: 4, type: "history.older-request", trigger: "viewport-user" },
141 { t: 5, type: "transcript.scroll-write", owner: "unknown-writer" },
142 ]), [
143 { code: "settle-before-paint-ready", intent: 7 },
144 { code: "navigation-session-count-changed", intent: 7, count: 2 },
145 { code: "viewport-older-without-user-input", count: 1 },
146 { code: "unknown-scroll-writer", count: 1 },
147 ], "automatic analysis reports ordering, paging, catalog, and writer anomalies");
148
149 assert.deepEqual(analyzeFrontendDiagnosticAnomalies([
150 { t: 0, type: "history.viewport-permit" },
151 { t: 1, type: "history.older-request", trigger: "viewport-user" },
152 ]), [], "a viewport page request consumes one explicit user permit without a false anomaly");
153 assert.deepEqual(analyzeFrontendDiagnosticAnomalies([
154 { t: 0, type: "navigation.begin", intent: 9 },
155 { t: 1, type: "navigation.settle", intent: 9, outcome: "failed" },
156 ]), [], "a failed data terminal may release its mask without a paint-ready false positive");
157
158 console.log("frontend diagnostics tests passed");
159
159 lines TYPESCRIPT