返回 DeepSeek-Reasonix
attachment-display.test.ts
根目录 / desktop / frontend / src / __tests__ / attachment-display.test.ts
1 // Run: tsx src/__tests__/attachment-display.test.ts
2
3 import { baseName, formatAttachmentRefForDisplay, formatAttachmentRefForSubmit, parseAttachmentRefsForDisplay, replaceAttachmentRefsForDisplay, restoreAttachmentRefsForSubmit, sortDisplayAttachments } from "../lib/attachmentDisplay";
4 import { appendHistoryAttachmentRefs } from "../lib/historyAttachmentRefs";
5
6 let passed = 0;
7 let failed = 0;
8
9 function eq(a: unknown, b: unknown, label: string) {
10 if (JSON.stringify(a) === JSON.stringify(b)) {
11 process.stdout.write(` PASS ${label}\n`);
12 passed += 1;
13 } else {
14 process.stdout.write(` FAIL ${label}: expected ${JSON.stringify(b)}, got ${JSON.stringify(a)}\n`);
15 failed += 1;
16 }
17 }
18
19 console.log("\nattachment display");
20
21 const named = parseAttachmentRefsForDisplay(
22 "review @[DS30000.sl2](.reasonix/attachments/clipboard-20260610-121238.444775-000002.sl2) and @[park.png](.reasonix/attachments/clipboard-20260610-121238.444775-000001.png)",
23 );
24
25 eq(named.text, "review and", "removes named display refs from message text");
26 eq(
27 named.attachments.map((a) => ({ path: a.path, name: a.name, kind: a.kind, ext: a.ext })),
28 [
29 {
30 path: ".reasonix/attachments/clipboard-20260610-121238.444775-000002.sl2",
31 name: "DS30000.sl2",
32 kind: "file",
33 ext: "SL2",
34 },
35 {
36 path: ".reasonix/attachments/clipboard-20260610-121238.444775-000001.png",
37 name: "park.png",
38 kind: "image",
39 ext: "PNG",
40 },
41 ],
42 "preserves original display names for attachment cards",
43 );
44 eq(
45 sortDisplayAttachments(named.attachments).map((a) => a.name),
46 ["park.png", "DS30000.sl2"],
47 "sorts images before files while keeping groups stable",
48 );
49 eq(
50 replaceAttachmentRefsForDisplay("see @[DS30000.sl2](.reasonix/attachments/clipboard-20260610-121238.444775-000002.sl2)"),
51 "see [file:DS30000.sl2]",
52 "compact previews use named display refs",
53 );
54 eq(
55 restoreAttachmentRefsForSubmit("review @[DS30000.sl2](.reasonix/attachments/clipboard-20260610-121238.444775-000002.sl2), then @[park.png](.reasonix/attachments/clipboard-20260610-121238.444775-000001.png)"),
56 "review @.reasonix/attachments/clipboard-20260610-121238.444775-000002.sl2, then @.reasonix/attachments/clipboard-20260610-121238.444775-000001.png",
57 "restores named display refs for submit",
58 );
59 eq(
60 formatAttachmentRefForDisplay({ path: ".reasonix/attachments/clipboard-20260610-121238.444775-000001.png", name: "park.png", source: "attachment" }),
61 "@[park.png](.reasonix/attachments/clipboard-20260610-121238.444775-000001.png)",
62 "formats attachment display refs for edit replay",
63 );
64 eq(
65 formatAttachmentRefForSubmit({ path: ".reasonix/attachments/clipboard-20260610-121238.444775-000001.png" }),
66 "@.reasonix/attachments/clipboard-20260610-121238.444775-000001.png",
67 "formats raw attachment refs for edit replay submit",
68 );
69 const session = parseAttachmentRefsForDisplay(appendHistoryAttachmentRefs("see", [{ digest: "aa".repeat(32), name: "shot.png", mime: "image/png" }]));
70 eq(session.attachments[0]?.path, `attachment:${"aa".repeat(32)}`, "history attachments use digest paths");
71 eq(session.attachments[0]?.kind, "image", "history attachments are images");
72 const parsedDraft = parseAttachmentRefsForDisplay("see @[photo.png](draft:0123456789abcdef0123456789abcdef)");
73 eq(parsedDraft.attachments[0]?.path, "draft:0123456789abcdef0123456789abcdef", "draft credentials parse as display attachments");
74 eq(
75 [...session.attachments, ...parsedDraft.attachments].map((a) => a.path),
76 [session.attachments[0].path, parsedDraft.attachments[0].path],
77 "projects structured history attachments beside parsed draft refs",
78 );
79
80 eq(baseName("C:\\Users\\Abyss\\Desktop\\DS30000.sl2"), "DS30000.sl2", "extracts Windows path basenames");
81 eq(baseName("/Users/abyss/Desktop/park.png"), "park.png", "extracts POSIX path basenames");
82
83 const escaped = parseAttachmentRefsForDisplay("look at @docs/my\\ report\\ 2026.pdf now");
84 eq(escaped.text, "look at now", "removes an escaped workspace ref from message text");
85 eq(
86 escaped.attachments.map((a) => ({ path: a.path, name: a.name, kind: a.kind, source: a.source })),
87 [{ path: "docs/my report 2026.pdf", name: "my report 2026.pdf", kind: "file", source: "workspace" }],
88 "escaped workspace ref becomes one full badge with the unescaped path",
89 );
90 eq(
91 formatAttachmentRefForDisplay({ path: "docs/my report 2026.pdf", name: "my report 2026.pdf", source: "workspace" }),
92 "@docs/my\\ report\\ 2026.pdf",
93 "workspace display refs escape whitespace for lossless edit replay",
94 );
95 eq(
96 formatAttachmentRefForSubmit({ path: "docs/my report 2026.pdf" }),
97 "@docs/my\\ report\\ 2026.pdf",
98 "workspace submit refs escape whitespace so @-token parsing resolves them",
99 );
100
101 console.log(`\n${passed} passed, ${failed} failed, ${passed + failed} total`);
102 if (failed > 0) process.exit(1);
103
103 lines TYPESCRIPT