# 医梦统一入口客户端 Web Demo — 测试报告 **日期**: 2026-06-02 **版本**: 0.1.0 **分支**: 统一入口客户端演示 **测试环境**: Windows 11 / Node.js 20.19.4 / Chrome (本地) --- ## 概览 | 层级 | 测试文件 | 测试用例 | 通过 | 失败 | 通过率 | |------|---------|---------|------|------|--------| | 单元测试 | 5 | 25 | 25 | 0 | 100% | | E2E 测试 | 2 | 4 | 4 | 0 | 100% | | **合计** | **7** | **29** | **29** | **0** | **100%** | --- ## 一、单元测试(Vitest) ``` PASS tests/unit/sse.spec.ts (6 tests / 8ms) PASS tests/unit/apiClient.spec.ts (3 tests / 17ms) PASS tests/unit/terminalStore.spec.ts (7 tests / 15ms) PASS tests/unit/doctorAssistantFigure.spec.ts (1 test / 42ms) PASS tests/unit/cardRenderer.spec.ts (8 tests / 53ms) ───────────────────────────────────────────────────────── Test Files 5 passed (5) Tests 25 passed (25) Duration 2.47s ``` ### 1.1 SSE 解析器 (`sse.spec.ts`) — 6 通过 | # | 测试用例 | 状态 | 说明 | |---|---------|------|------| | 1 | parses named SSE events with JSON data and preserves remainder | PASS | 正确解析 `event:`/`data:` 配对并保留未完成片段 | | 2 | accumulates across multiple chunks | PASS | 跨 chunk 拼接,收到完整 `\n\n` 后再输出事件 | | 3 | handles multiple events in one chunk | PASS | 单次收到多个 `\n\n` 分隔的事件时全部解析 | | 4 | ignores malformed data events without throwing | PASS | data 非合法 JSON 时不抛异常,返回 error 类型事件 | | 5 | skips events without both event and data lines | PASS | 缺失 event 或 data 行的事件静默跳过 | | 6 | handles all six SSE event types | PASS | 全部 6 种类型 (task_updated / message_delta / message_completed / card_created / error / completed) 均正确解析 | ### 1.2 HMAC 辅助函数 (`apiClient.spec.ts`) — 3 通过 | # | 测试用例 | 状态 | 说明 | |---|---------|------|------| | 1 | hashes body as lowercase hex sha256 | PASS | `{"a":1}` 的 SHA-256 散列与预期一致 | | 2 | produces consistent hash for same input | PASS | 相同输入产生相同哈希 | | 3 | produces different hashes for different input | PASS | 不同输入产生不同哈希 | ### 1.3 全局状态 Store (`terminalStore.spec.ts`) — 7 通过 | # | 测试用例 | 状态 | 说明 | |---|---------|------|------| | 1 | starts in idle right-panel mode with no active card | PASS | 初始状态:idle,无 activeCard | | 2 | switches to task mode when a card is active | PASS | setActiveCard → contextPanelMode = task | | 3 | switches to completed mode for appointment-success card | PASS | 挂号成功卡片 → contextPanelMode = completed | | 4 | switches to error mode when error message is set | PASS | setError → contextPanelMode = error | | 5 | resets to idle clears task, card and error | PASS | resetToIdle 清空 task / activeCard / errorMessage | | 6 | appends assistant delta correctly | PASS | appendAssistantDelta 流式拼接文本 | | 7 | completes assistant message marks streaming false | PASS | completeAssistantMessage 标记流结束 | ### 1.4 医生形象组件 (`doctorAssistantFigure.spec.ts`) — 1 通过 | # | 测试用例 | 状态 | 说明 | |---|---------|------|------| | 1 | renders the static doctor assistant image and no voice controls | PASS | 渲染医生图片、文字说明,无语音/按钮交互,无"可听""可说" | ### 1.5 卡片渲染器 (`cardRenderer.spec.ts`) — 8 通过 | # | 测试用例 | 状态 | 说明 | |---|---------|------|------| | 1 | renders department card by cardKey | PASS | `department-selection` → 渲染"推荐科室""神经内科" | | 2 | renders doctor selection card | PASS | `doctor-selection` → 渲染"选择医生""李明""主任医师" | | 3 | renders time slot selection card | PASS | `time-slot-selection` → 渲染"选择时间""明天 09:30-09:45" | | 4 | renders confirm appointment card | PASS | `confirm-appointment` → 渲染"确认挂号信息""神经内科""25 元" | | 5 | renders payment QR card with mock label | PASS | `payment-qrcode` → 必须包含"联调演示 / Mock 支付" | | 6 | renders appointment success card with mock label | PASS | `appointment-success` → 渲染"A023",包含 mock 标签 | | 7 | renders error card for unknown card key | PASS | 未知 cardKey → 显示"暂不支持的卡片类型" | | 8 | emits action event when card button is clicked | PASS | 按钮点击正确向上 emit action 事件 | --- ## 二、E2E 测试(Playwright) ``` PASS [desktop-1440] visual-layout (1.5s) PASS [desktop-1920] visual-layout (1.8s) PASS [desktop-1440] registration-flow (1.9s) PASS [desktop-1920] registration-flow (2.2s) ───────────────────────────────────────────────────────── 4 passed (6.4s) ``` ### 2.1 视觉布局验收 (`visual-layout.spec.ts`) — 2 通过 | 视口 | 状态 | 验收点 | |------|------|--------| | 1440×900 | PASS | 标题"医梦门诊助手"可见;左侧"说出需求,我来判断下一步"可见;医生助手图片存在;"静态形象展示"文案存在;语音/发送按钮在中间区域;无"智能挂号"等大按钮;无横向滚动 | | 1920×1080 | PASS | 同上 | ### 2.2 挂号全流程 (`registration-flow.spec.ts`) — 2 通过 | 视口 | 状态 | 验收点 | |------|------|--------| | 1440×900 | PASS | 输入症状 → 科室推荐 → 选择神经内科 → 选择李明医生 → 选择 09:30 → 确认挂号 → Mock 支付 → 挂号成功(A023) | | 1920×1080 | PASS | 同上 | --- ## 三、构建验证 ``` pnpm build PASS (vue-tsc --noEmit + vite build) ``` 产物: ``` dist/index.html 0.41 kB (gzip: 0.30 kB) dist/assets/index-gsDAE_p7.css 10.44 kB (gzip: 2.28 kB) dist/assets/index-9PUkZENd.js 84.33 kB (gzip: 32.96 kB) ``` --- ## 四、覆盖范围分析 | 模块 | 单元测试 | E2E | 覆盖状态 | |------|:---:|:---:|------| | SSE 解析器 (`sse.ts`) | 6 | - | 完全覆盖 | | HMAC 辅助 (`hmac.ts`) | 3 | - | 完全覆盖 | | API 客户端 (`client.ts`) | - | - | Demo 模式已间接覆盖,真实模式待后端联调 | | 状态 Store | 7 | - | 完全覆盖 | | 医生形象组件 | 1 | 2 | 完全覆盖 | | 卡片渲染器 | 8 | 2 | 完全覆盖 | | 对话面板 | - | 2 | E2E 间接覆盖 | | 三栏布局 Shell | - | 2 | E2E 间接覆盖 | | 挂号进度组件 | - | 2 | E2E 间接覆盖 | --- ## 五、已知缺口 1. **API 客户端真实模式** — `client.ts` 的真实 HTTP 请求分支需要后端 SSE 接口就绪后才能验证 2. **医生 PNG 图片** — 当前使用 SVG 占位,设计稿指定了真实 PNG(macOS 路径未同步至 Windows 环境) 3. **语音功能** — 按设计在 `out of scope` 范围内,当前仅展示按钮并给出提示 4. **hmac.ts 真实签名** — Demo 签名仅用于本地演示,真实 HMAC 签名待联调时接入 5. **应用启动引导** — 设备注册、心跳、场景加载流程待后端就绪后覆盖