返回 DeepSeek-Reasonix
conversation-width.test.ts
根目录 / desktop / frontend / src / __tests__ / conversation-width.test.ts
1 // Run: tsx src/__tests__/conversation-width.test.ts
2
3 import { readFileSync } from "node:fs";
4 import { dirname, resolve } from "node:path";
5 import { fileURLToPath } from "node:url";
6 import {
7 applyConversationWidth,
8 CONVERSATION_WIDTH_STORAGE_KEY,
9 FULL_CONVERSATION_MAX_WIDTH,
10 getCachedConversationWidth,
11 normalizeConversationWidth,
12 STANDARD_CONVERSATION_MAX_WIDTH,
13 } from "../lib/conversationWidth";
14
15 const testDir = dirname(fileURLToPath(import.meta.url));
16 const stylesSource = readFileSync(resolve(testDir, "../styles.css"), "utf8");
17 const settingsSource = readFileSync(resolve(testDir, "../components/SettingsPanel.tsx"), "utf8");
18
19 let passed = 0;
20 let failed = 0;
21
22 function ok(value: boolean, label: string) {
23 if (value) {
24 process.stdout.write(` PASS ${label}\n`);
25 passed += 1;
26 } else {
27 process.stdout.write(` FAIL ${label}\n`);
28 failed += 1;
29 }
30 }
31
32 const attrs = new Map<string, string>();
33 const styleProps = new Map<string, string>();
34 const storage = new Map<string, string>();
35
36 (globalThis as unknown as { document: unknown }).document = {
37 documentElement: {
38 setAttribute(name: string, value: string) {
39 attrs.set(name, value);
40 },
41 style: {
42 setProperty(name: string, value: string) {
43 styleProps.set(name, value);
44 },
45 },
46 },
47 };
48
49 (globalThis as unknown as { localStorage: unknown }).localStorage = {
50 getItem(key: string) {
51 return storage.get(key) ?? null;
52 },
53 setItem(key: string, value: string) {
54 storage.set(key, value);
55 },
56 };
57
58 console.log("\nconversation width contract");
59
60 ok(normalizeConversationWidth(undefined) === "standard", "missing values use the backward-compatible standard width");
61 ok(normalizeConversationWidth("unknown") === "standard", "unknown values use the standard width");
62 ok(normalizeConversationWidth("full") === "full", "full is preserved");
63
64 storage.set(CONVERSATION_WIDTH_STORAGE_KEY, "full");
65 ok(getCachedConversationWidth() === "full", "early-paint cache restores full width");
66
67 applyConversationWidth("standard");
68 ok(styleProps.get("--maxw") === STANDARD_CONVERSATION_MAX_WIDTH, "standard width remains fixed at 960px");
69
70 applyConversationWidth("full");
71 ok(styleProps.get("--maxw") === FULL_CONVERSATION_MAX_WIDTH, "full width never becomes narrower than standard");
72 ok(attrs.get("data-conversation-width") === "full", "active width is exposed on the root element");
73 ok(storage.get(CONVERSATION_WIDTH_STORAGE_KEY) === "full", "applied width refreshes the early-paint cache");
74
75 ok(stylesSource.includes("--maxw-inner: 100%;"), "nested transcript content uses an unbounded inner width");
76 ok(
77 /\.warm-turn__body\s*>\s*\*\s*\{[^}]*max-width:\s*var\(--maxw-inner\)/s.test(stylesSource) &&
78 /\.readonly-batch__body\s*>\s*\*,\s*\.turn-collapse__body\s*>\s*\*\s*\{[^}]*max-width:\s*var\(--maxw-inner\)/s.test(stylesSource),
79 "nested transcript containers do not compound the outer percentage width",
80 );
81 ok(!stylesSource.includes("--maxw: 90%;"), "stylesheets cannot reintroduce the narrow 90 percent override");
82
83 ok(
84 settingsSource.includes("setConversationWidth(applyConversationWidth(s.conversationWidth))"),
85 "authoritative desktop settings replace the early-paint cache",
86 );
87 ok(
88 settingsSource.includes("conversationWidth: normalizeConversationWidth(view.conversationWidth)"),
89 "older settings payloads without the field normalize to standard",
90 );
91
92 console.log(`\n${passed} passed, ${failed} failed`);
93 if (failed > 0) process.exit(1);
94
94 lines TYPESCRIPT