test(workbench): 增加 DOCX/XLSX 导出与会话隔离单元测试

- 验证 DOCX 二进制 Buffer 生成、TextRun 解析与 Blob 输出
- 验证 XLSX 多表提取、自适应列宽与工作簿 Sheet 命名规范
- 验证 sess-001 与 sess-002 对话隔离及动态追加互不串线

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
WeiCHEN
2026-09-13 02:50:19 +00:00
committed by weichen
co-authored by Cursor
parent 2fcf02200e
commit ff1eaab820
2 changed files with 169 additions and 0 deletions
+81
View File
@@ -0,0 +1,81 @@
import test from 'node:test';
import assert from 'node:assert/strict';
import { DEFAULT_MESSAGES, DEFAULT_SESSIONS } from './storage';
import { ChatMessage } from '../types/workbench';
test('多项目会话消息隔离测试 (Multi-project Session Messages Strict Isolation)', () => {
// 1. 验证预设会话消息按 sessionId 严格分离
const sess1Msgs = DEFAULT_MESSAGES.filter((m) => m.sessionId === 'sess-001');
const sess2Msgs = DEFAULT_MESSAGES.filter((m) => m.sessionId === 'sess-002');
assert.ok(sess1Msgs.length >= 2, 'sess-001 应当包含其专属消息');
assert.ok(sess2Msgs.length >= 2, 'sess-002 应当包含其专属消息');
// 验证 sess-001 包含内窥镜关键字,不包含超声探头
const sess1Combined = sess1Msgs.map((m) => m.content).join(' ');
assert.ok(sess1Combined.includes('荧光内窥镜'));
assert.ok(!sess1Combined.includes('超声声输出安全标准'));
// 验证 sess-002 包含超声探头关键字,不包含腹腔镜初稿
const sess2Combined = sess2Msgs.map((m) => m.content).join(' ');
assert.ok(sess2Combined.includes('便携式掌上无线超声诊断仪'));
assert.ok(!sess2Combined.includes('4K超高清荧光内窥镜系统立项与可行性报告'));
// 2. 模拟向 sess-001 追加一条新消息
const allMessages: ChatMessage[] = [...DEFAULT_MESSAGES];
const newMsgSess1: ChatMessage = {
id: 'm-new-1',
sessionId: 'sess-001',
role: 'user',
content: '请测算一下双棱镜分光成本',
timestamp: '14:30',
};
allMessages.push(newMsgSess1);
// 3. 验证此时切到 sess-002 时,绝不出现新消息
const filteredSess2 = allMessages.filter((m) => m.sessionId === 'sess-002');
assert.equal(filteredSess2.length, sess2Msgs.length, 'sess-002 的消息条数应当完全不受 sess-001 变动的影响');
assert.ok(!filteredSess2.some((m) => m.content.includes('双棱镜分光成本')));
// 4. 验证此时切到 sess-001 时,准确多了一条消息
const filteredSess1 = allMessages.filter((m) => m.sessionId === 'sess-001');
assert.equal(filteredSess1.length, sess1Msgs.length + 1);
assert.ok(filteredSess1.some((m) => m.content.includes('双棱镜分光成本')));
});
test('新建项目会话独立初始化隔离测试 (New Session Spawning & Isolation)', () => {
const allSessions = [...DEFAULT_SESSIONS];
const newSessId = 'sess-new-999';
const newSess = {
sessionId: newSessId,
projectId: 999,
title: '神经外科双极电凝系统',
deviceType: '高频手术设备',
stage: 'V0.1' as const,
stageLabel: 'V0.1 需求摸底',
messageCount: 1,
updatedAt: '刚刚',
};
allSessions.unshift(newSess);
const initialMsgs: ChatMessage[] = [
...DEFAULT_MESSAGES,
{
id: 'm-init-999',
sessionId: newSessId,
role: 'system',
content: '水木东方协同参谋小队已就位,当前项目【神经外科双极电凝系统】进入需求摸底阶段。',
timestamp: '刚刚',
},
];
// 检查新项目消息隔离
const sess999Msgs = initialMsgs.filter((m) => m.sessionId === newSessId);
assert.equal(sess999Msgs.length, 1);
assert.ok(sess999Msgs[0].content.includes('神经外科双极电凝系统'));
// 检查原项目消息数量未变
assert.equal(initialMsgs.filter((m) => m.sessionId === 'sess-001').length, 2);
assert.equal(initialMsgs.filter((m) => m.sessionId === 'sess-002').length, 2);
});
+88
View File
@@ -0,0 +1,88 @@
import test from 'node:test';
import assert from 'node:assert/strict';
import { markdownToBlockAST } from './markdownToBlock';
import { buildDocxModel, exportDocumentToDocx, parseInlineTextRuns } from './docxRenderer';
import { buildXlsxWorkbook, exportDocumentToXlsx } from './xlsxRenderer';
import { Packer } from 'docx';
const SAMPLE_MD = `# 4K超高清荧光内窥镜系统立项与可行性报告
本产品主要用于微创腹腔手术中的组织成像与荧光导航。
> **[合规依据]** 本项目需严格遵守 GB 9706.1-2020 医用电气安全标准。
## 关键技术指标与参数对比
| 参数项 | 指标要求 | 检验依据 | 验证结果 |
| 光学分辨率 | 4K (3840x2160) | YY 0068.1 | 符合 |
| 荧光波长 | 805nm 近红外 | 临床验证 | 符合 |
| 延迟时间 | < 35ms 超低延迟 | 内部实测 | 优于竞品 |
## 研发工时与费用测算
| 阶段 | 责任工程师 | 预计工时 (h) | 费率 (元/h) | 小计金额 (万元) |
| V0.1 需求摸底 | 光学方案专家 | 80 | 600 | 4.80 |
| V0.5 方案对齐 | FPGA硬件工程师 | 160 | 450 | 7.20 |
| V1.0 样机研制 | 嵌入式与算法架构师 | 240 | 500 | 12.00 |
$$
SNR = 10 \\cdot \\log_{10}\\left(\\frac{P_{signal}}{P_{noise}}\\right)
$$
`;
test('DOCX 渲染器行内文本解析测试 (parseInlineTextRuns)', () => {
const text = '依据 **GB 9706.1-2020** 检验,*延迟* 小于 `35ms`。';
const runs = parseInlineTextRuns(text);
assert.ok(runs.length >= 4);
});
test('DOCX 渲染器全量编译测试 (buildDocxModel & exportDocumentToDocx)', async () => {
const ast = markdownToBlockAST(SAMPLE_MD, {
docId: 'doc_docx_test_001',
taskKey: 'feasibility_reg',
author: '张工',
reviewer: '李主管',
approver: '王总监',
version: 'V1.0',
lifecycleState: 'drafting',
});
const doc = buildDocxModel(ast);
assert.ok(doc);
// 验证 Packer 编译输出 Buffer 大小正常
const buffer = await Packer.toBuffer(doc);
assert.ok(buffer.length > 5000, `生成的 DOCX Buffer 应当大于 5KB,实际为 ${buffer.length} 字节`);
// 验证 exportDocumentToDocx 输出 Blob 正常
const blob = await exportDocumentToDocx(ast);
assert.equal(blob.type, 'application/vnd.openxmlformats-officedocument.wordprocessingml.document');
assert.ok(blob.size > 5000);
});
test('XLSX 渲染器多表提取与工作簿编译测试 (buildXlsxWorkbook & exportDocumentToXlsx)', async () => {
const ast = markdownToBlockAST(SAMPLE_MD, {
docId: 'doc_xlsx_test_001',
taskKey: 'feasibility_reg',
author: '张工',
reviewer: '李主管',
approver: '王总监',
version: 'V1.0',
lifecycleState: 'drafting',
});
const wb = buildXlsxWorkbook(ast);
assert.ok(wb);
assert.ok(wb.SheetNames.length >= 3, `应该包含概览 Sheet 和 2 个表格 Sheet,实际有: ${wb.SheetNames.join(', ')}`);
assert.equal(wb.SheetNames[0], '文档概览与签署');
// 验证表 1 数据
const sheet1 = wb.Sheets[wb.SheetNames[1]];
assert.ok(sheet1);
// 验证 exportDocumentToXlsx 输出 Blob 正常
const blob = await exportDocumentToXlsx(ast);
assert.equal(blob.type, 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
assert.ok(blob.size > 1000);
});