Repository Wiki
deepseek-ai/deepseek-harness

输入、审批与交互操作

本页从 Web 端到会话结果,说明输入框提交、待审批面板接管以及批准后的恢复行为。依据为浏览器端到端测试;未读取客户端组件和服务端实现,因此将测试可验证的外部契约与内部实现严格区分。

Purpose and Scope

范围限于输入、审批与交互操作的用户可见路径:输入长提示、切换访问模式、等待审批、通过按钮或键盘批准、观察会话事件和输入框恢复。审批规则、权限判定引擎、会话事件持久化、Web 构建与部署不属于本页;这些内部实现细节在已读取的源码中未找到。对于会话存储及权限策略,应参阅相应专题,而不是把测试观察当作实现保证。审批端到端测试。

Overview

测试先用 launchWebScaffold 建立可认证工作区,借助浏览器定位 [data-composer-input],设置 Read Only 模式并按 Enter 发送提示;待 [data-approval-key] 出现后,在审批面板中允许一次操作。测试既检查较长命令的滚动区域与按钮可达性,也核对 approval/decided 事件、工作区文件、回复以及审批面板消失后的输入框重新可用。准备过程、提交和等待、结论断言。

Architecture

下面仅表示测试代码实际连接或观测到的组件、事件和 DOM 元素,不代表未经读取的内部模块调用关系。

Loading diagram...

Source: approval-composer.e2e.ts

Scaffold 暴露 ctx 的 session/event 订阅;测试将事件累积起来,与页面操作后的结果进行交叉检查。这一结构避免仅凭按钮点击就认为命令已执行;文件内容和最终工作区快照提供另一层可观测证据。事件订阅、结果检查。

实际交互流程

1. 环境与事件观察

测试根据 webSnapshotMode() 选择录制或重放:录制时只测试按钮路径;非录制模式同时测试按钮与键盘路径。重放时以 replayFixture、paceMs: 15 和 compareReplaySession: true 初始化 scaffold。测试在浏览器导航前订阅 session/event,因此后续可检验批准结果。模式选择与准备。

2. 提交输入并进入审批

测试先填写 40 行探针文本,从运行中的 [data-input-scroll] 读取 composer 的 clientHeight,清空后选择 Read Only。它先创建 whenTurnSettled 等待,再填入 PROMPT、按 Enter,等待 [data-approval-key] 出现,并确认 [data-approval-scroll] 内出现长命令的一部分。这里的 PROMPT 要求写入 notes.txt 并回复 DONE;测试生成 220 个不同 token,使待审批命令足够长,以验证溢出布局。测试输入生成、输入提交。

typescript
1const input = page.locator('[data-composer-input]').first() 2await input.waitFor({ timeout: 10_000 }) 3 4// Derive the expected cap from the live composer instead of duplicating its pixel value. 5await input.fill(CAP_PROBE) 6const composerCap = await input.evaluate(el => el.closest('[data-input-scroll]')?.clientHeight ?? 0) 7expect(composerCap).toBeGreaterThan(0) 8await input.fill('')

Source: approval-composer.e2e.ts

3. 审批、收束和恢复

面板提供 Allow once 按钮;替代路径为聚焦审批滚动区域后按 Enter。测试等待回合收束,再断言最近一次 approval/decided 含 allowed-once,工作区文件包含提示中的 token,页面出现 DONE,审批面板被移除,composer 首个输入框重新可用。录制路径则记录 fixture 并校验最终工作区快照,提前返回。批准和断言。

Loading diagram...

Source: approval-composer.e2e.ts

序列图中的两个批准分支来自同一测试用例的 method 条件;它们不会在一次执行中同时触发。分支和结果。

Usage Examples

切换访问模式并发送提示

以下是测试实际使用的浏览器操作;PROMPT 在同一文件中定义为包含大量 token 的写文件请求。先等待模式标签变化,再提交输入,可以让测试在预期的 Read Only 状态下触发审批路径。提示定义。

typescript
1await page.locator('[aria-label^="Access mode"]').click() 2await page.getByRole('menuitem', { name: 'Read Only' }).click() 3await expect.poll( 4 () => page.locator('[aria-label="Access mode, current: Read Only"]').count(), 5 { timeout: 15_000 }, 6).toBe(1) 7 8const settled = scaffold.whenTurnSettled(MODE === 'record' ? 240_000 : 60_000) 9await input.fill(PROMPT) 10await input.press('Enter')

Source: approval-composer.e2e.ts

两种批准方式

typescript
1if (method === 'button') await panel.getByRole('button', { name: 'Allow once' }).click() 2else { 3 await scroll.focus() 4 await page.keyboard.press('Enter') 5}

Source: approval-composer.e2e.ts

布局边界与失败检测

长命令测试分别把视口改为 900×1000 和 900×700;它要求审批文本确实可以滚动、审批区域的可见高度与实时测得的 composer 上限相差小于 1 像素,且两个操作按钮既在视口内,也在卡片底部以内。这里使用运行时尺寸而非复制 CSS 数值,可检测共享高度约束退化;小于 1 像素的容差用于处理亚像素布局差异。几何检查。

typescript
1expect(geometry.buttons).toBe(2) 2expect(geometry.scrolls).toBe(true) 3// The panel and composer share one cap; allow sub-pixel layout variance. 4expect(Math.abs(geometry.capped - composerCap)).toBeLessThan(1) 5expect(geometry.actionsTop).toBeGreaterThan(0) 6expect(geometry.actionsBottom).toBeLessThanOrEqual(geometry.viewport) 7expect(geometry.actionsBottom).toBeLessThanOrEqual(geometry.cardBottom)

Source: approval-composer.e2e.ts

测试失败时保存截图;非录制路径验证 console 的 pageErrors 和 warnings 都为空,并以轮询等待 DONE 和输入框恢复。显式超时覆盖初始输入、模式切换、审批面板和回合收束等异步边界。测试使用 sessionEvents.filter(...).at(-1) 检查最近的批准事件,但未由此证明生产代码的并发仲裁或事件持久性;实现细节在已读取源码中未找到。失败截图与等待、收尾检查。

测试配置与运行边界

项目类型测试中的值作用
MODEwebSnapshotMode() 的结果record 或其他模式record 时仅运行按钮场景,其他模式运行按钮和键盘场景。
replayFixture文件路径FIXTURE非录制模式重放 session.v3.jsonl。
paceMs数字15非录制模式传入 launchWebScaffold 的重放参数。
compareReplaySession布尔值true非录制模式传入 scaffold。
whenTurnSettled 超时毫秒录制 240_000;否则 60_000等待回合结束。

以上为测试参数,不能推断是产品配置默认值。模式与 scaffold 参数、回合超时。

API 与扩展边界

可确认的只是测试调用接口:launchWebScaffold(...) 返回供测试使用的 scaffold;scaffold.ctx.on('session/event', ...) 接收事件;scaffold.whenTurnSettled(...) 被等待以取得 sessionId。其完整类型签名、异常语义与内部实现未在已读取源码中找到,故不将其描述为对外稳定 API。调用点、等待及返回值、使用会话 ID。扩展这类交互回归测试时,可沿用两种输入途径、事件和文件结果交叉断言,以及从实际 DOM 测量几何上限的方式;不要假设未检查的产品内部挂钩。

Sources

(1 files)