跳转至

控制 UI、TUI 和 E2E 泳道

控制 UI、TUI 和扩展通道

  • 浏览器 MCP 契约: pnpm test:e2e:browser-mcp 会安装固定版本的 Playwright Chromium,并通过 stdio 针对一次性浏览器配置文件启动已配置的 Chrome DevTools MCP 服务器。它覆盖原生操作、跨条件等待的 refs、frame 标签、导航策略检查,以及经过 npm/pnpm 打包和离线 npm 安装后补丁依赖的保留。路径过滤的 Browser MCP contract 工作流会在 MCP 实现和依赖变更时运行此命令。其 contract-bun 作业会在固定版本的 Bun fork 上运行 Chromium 契约文件(OPENCLAW_VITEST_RUNTIME=bun),这是 macOS 和 Linux 桌面应用唯一的运行时。要验证候选服务器构建,请将 OPENCLAW_BROWSER_MCP_TEST_COMMAND 设置为其可执行启动器。启动器必须转发其参数,并为坐标操作启用 --experimentalVision;OpenClaw 提供端点和结构化内容标志。用该证明记录服务器来源/版本。这些测试不会附加到用户的 Chrome,也不需要模型凭据。
  • 控制 UI E2E: pnpm test:ui:e2e 运行 Vitest + Playwright 通道,通常针对模拟的 Gateway WebSocket。四个资源组保留两个执行阶段:ui-e2e-bundled 和 ui-e2e-standalone 首先运行,总共最多两个 worker;然后 ui-e2e-serial 和 ui-e2e-serial-standalone 共享一个 worker。两个 bundle 消费者会延迟共享一个临时 UI bundle/预览,直到调用关闭。Standalone 项目拥有自己的 fixture、source 或 custom-build 服务器;仅选择 standalone 套件可避免共享 bundle 构建。每个选中的项目都会接收 Chromium 元数据,新的 E2E 文件默认采用并行 bundled 所有权。根配置保留完整发现清单:ui/src/**/*.e2e.test.ts 以及 QA Lab media-transcript 和 OpenClaw-delegation real-Gateway 套件。共享 mocks/controls 位于 ui/src/test-helpers/control-ui-e2e.ts。某些套件会启动隔离的真实 Gateway;OPENCLAW_UI_E2E_SKIP_REAL_GATEWAY=1 会排除它们。pnpm test:e2e 包含此通道,资源组没有额外 CI 作业。仅当干净的 Linux/浏览器一致性是证明的一部分时,才使用 Testbox/Crabbox。在 linked worktree 中,node scripts/run-vitest.mjs run --config test/vitest/vitest.ui-e2e.config.ts --configLoader runner ui/src/e2e/chat-flow.messaging.e2e.test.ts 可避免针对目标本地运行进行 pnpm 依赖协调。
  • 控制 UI 真实 Gateway 审批证明: 针对带有 mock provider 的隔离 Gateway,检查默认和显式 Full Access 委托。在运行目标证明之前构建运行时:
pnpm build qaRuntime
node scripts/run-vitest.mjs run --config test/vitest/vitest.ui-e2e.config.ts \
  --configLoader runner extensions/qa-lab/src/control-ui-openclaw-delegation.real-gateway.e2e.test.ts
  • TUI PTY 测试: node scripts/run-vitest.mjs run --config test/vitest/vitest.tui-pty.config.ts 运行快速的 fake-backend PTY 通道。OPENCLAW_TUI_PTY_INCLUDE_LOCAL=1 或 pnpm tui:pty:test:watch --mode local 运行较慢的 tui --local smoke 测试,它只 mock 外部模型端点。CI 还会在构建 dist/ 后设置 OPENCLAW_TUI_PTY_USE_BUILT_CLI=1;仅当 exact-head 构建产物已经存在时才使用该标志。断言稳定的可见文本或 fixture 调用,而不是原始 ANSI 快照。
  • pnpm test:extensions 和 pnpm test extensions 运行所有 extension/plugin 分片。重型 channel 插件、browser 插件和 OpenAI 作为专用分片运行;其他插件组保持批量。pnpm test extensions/<id> 运行一个 bundled 插件通道。
  • 浏览器原生主机: node scripts/run-vitest.mjs extensions/browser/src/browser/extension-install.native-host.e2e.test.ts 在 macOS 或 Linux 上针对已构建 dist 和合成安装状态运行真实 native messaging 启动器;它不会启动 Chrome 或 Gateway。Windows 会跳过此 POSIX 进程证明,因为 native bootstrap 在那里使用手动配对。E2E 负责人会在 worker 之前准备 artifacts。对于已构建的候选版本,在命令前加 OPENCLAW_E2E_USE_PREBUILT_DIST=1 以复用;缺失 artifacts 会导致测试失败。此用例属于 pnpm test:e2e,不属于 browser source 分片或未指定目标的 pnpm test 单元测试套件。Linux CI 会在 build-artifacts 中显式运行它,并验证一个 JSON 报告,证明确切命名的测试已通过。工作流仅跳过缺少此测试文件的冻结历史 checkout;该跳过是不可用证明,而不是通过或覆盖。
  • 具有同级测试的源文件会先映射到该同级测试,然后再回退到更宽的目录 glob。src/channels/plugins/contracts/test-helpers、src/plugin-sdk/test-helpers 和 src/plugins/contracts 下的 helper 编辑会使用本地 import graph 来运行导入测试,而不是在依赖路径精确时广泛运行每个分片。
  • 契约目录目标会扇出到其契约通道:pnpm test src/channels/plugins/contracts 运行四个 channel 契约配置,pnpm test src/plugins/contracts 运行 plugin 契约配置,因为通用 channels/plugins 项目排除了 contracts/**。
  • auto-reply 拆分为三个专用配置(core、top-level、reply),以便 reply harness 不会主导更轻量的 top-level status/token/helper 测试。
  • 选中的 plugin-sdk 和 commands 测试文件通过专用轻量通道路由,这些通道仅保留 test/setup.ts,将运行时重量级用例留在其现有通道上。
  • 基础 Vitest 配置默认为 pool: "threads" 和 isolate: false,并在仓库配置中启用共享的非隔离 runner。
  • pnpm test:channels 运行 vitest.channels.config.ts。

真实 Gateway 控制 UI 夹具生命周期

对于真实 Gateway 浏览器夹具,请使用来自 ui/src/e2e/control-ui-e2e-suite.test-support.ts 的 createControlUiE2eSuite。 suite.define(...) 拥有原生 hooks。每个原生 it 会将其测试上下文 传递给 suite.runScenario(context, ...),后者拥有获取、测试主体,以及 在另一个用例开始之前的最终化。通过 suite.newBrowserContext 和 suite.closeBrowserContext 获取和关闭浏览器上下文, 以便延迟获取和待关闭操作仍被拥有。

Retain test state immediately after createOpenClawTestState resolves, including when later config writes, imports, or startup fail. Hold original startup promises, not just their timeout wrappers. Close required producers before releasing state. For producers shared across cases, as in the MCP and auth suites, use the suite's resources.run, resources.close, and resources.release callbacks instead of independent beforeAll/afterAll cleanup. Resource acquisition follows shared server/browser acquisition; teardown joins cases and browser cleanup, closes required producers and servers, and releases state only after those closes succeed.

Failed or unjoined cleanup retains selectors and state, blocks later cases using this suite owner, and leaves native Vitest to terminate and join the isolated fork. Do not swallow close failures or restore the environment beneath unfinished work. The lifetime owner preserves existing hook, test, and action budgets.

Gateway close joins received WebSocket work and asynchronous connection cleanup, including cooperating background refreshes registered at their producer with trackAsyncWork. Connection-dependent worker sidecars must stop successfully before supervisor transports or other dependencies close; failure retains those dependencies and rejects shutdown. Register the actual operation, not just its response or timeout wrapper; cache eviction does not end its lifetime. withOpenClawTestState likewise joins registered callback descendants before releasing state. MCP requests observe both caller cancellation and their closing work owner, so shutdown cancels pending requests before joining handlers and disposing transports. These scopes do not automatically track arbitrary detached work or replace native test-timeout ownership. Other Gateway subsystems can retain documented bounded shutdown behavior, so close is not a guarantee of universal subsystem or descendant-process quiescence.

保留的 Control UI 证明

对于启动所有权变更,在浏览器恢复迁移完成之前执行已认证的 hello。项目和环境发现可以从 hello 开始;迁移完成不得重新获取这些目录,也不得使已接受的启动失效。将所有者变更、进程重启和迟到结果围栏分别覆盖。在重新渲染、输入和流式处理期间按 key 统计存储读取,且不记录凭据值。将路由 payload 字节数和已加载模块闭包与计时分开比较;CSS 所有权变更还需要保留截图,并在 New session 和 Chat 之间进行计算样式或几何检查。

迁移后的模拟和真实 Gateway 浏览器证明使用新的保留目录。 使用 suite.artifactDir 的场景捕获(包括 Logs 和 Usage)按测试尝试延迟分配;独立捕获按调用分配。MCP 一致性测试和认证传输各自在浏览器可用性检查之后分配一个套件拥有的目录,即使媒体捕获已禁用。认证传输 截图会等待有意义的内容以及呈现所有者的有限入场或调整大小动画,同时永久后代活动继续。 共享的 agent-file 捕获辅助函数在启用捕获时按模块求值分配一次,并在该模块的场景之间共享该目录。仅 Node 的 createControlUiE2eArtifactDir(scope, parentDir?) 辅助函数位于 ui/src/test-helpers/control-ui-e2e-artifacts.ts,会打印实际分配的路径。 显式父目录优先;否则使用修剪后的现有 OPENCLAW_UI_E2E_ARTIFACT_DIR,然后使用仓库的 .artifacts/control-ui-e2e 父目录。现有的功能特定目录控制和脚本输出参数选择父目录,并在其下使用唯一子目录。显式截图文件名 控制会保留 basename 并打印重定位后的路径。

保持捕获门控与分配独立:OPENCLAW_CAPTURE_UI_PROOF、 OPENCLAW_UI_E2E_RECORD 和输出存在门控保留其现有含义。 对于按尝试捕获,在场景执行期间或 beforeEach 中分配。 将同一所有者传递给共享捕获辅助函数,使截图、报告和视频 保持在一起。在一次尝试内区分阶段名称。在最终确定视频之前关闭浏览器上下文。

聊天加载性能真实 Gateway 套件在 loading-evidence.json 中记录浏览器时间戳,用于历史请求、数据发布、已提交行模型和视觉静默。窗格更新在滚动时仍可能显示旧行模型,因此探针会先验证保留行的索引已前进,再检查 50 ms 内没有转录变更、调整大小或滚动。 它分别记录该安静区间的开始和确认;确认延迟不是应用延迟。非零的 lateChanges 计数会使该静默样本失效。

使用无捕获的普通运行进行延迟比较。当 OPENCLAW_CAPTURE_UI_PROOF=1 时,套件还会保留截图、视频和 history-pagination.cpuprofile。分析和捕获会增加开销,并且 CPU 分析包括分页计时器开始之前的分析器启动。比较同一 fixture 和构建模式的重复运行;将旧测试驱动器的 墙钟计时与浏览器时间戳分开。

成功和失败的证据均被保留。清理是手动的:仅删除你拥有且已审阅完毕的精确目录。在重放之前,切勿递归删除 共享父目录。一次性构建/媒体 fixture 和临时原始视频有各自的清理。新捕获无法恢复被覆盖的证据; 不要将重放描述为恢复丢失的文件。

超时诊断在现有 OPENCLAW_UI_E2E_DIAGNOSTIC_DIR 或默认超时目录下分配新的子目录。每个子目录将其 原始 failure.private.json 报告和捕获的 failure.private.png 截图保留在本地,并附带一个允许列表中的 failure.public.json 摘要。自动 CI 上传 仅匹配 failure-*/failure.public.json;原始报告和截图保持私有。没有公共摘要的旧冻结目标不会产生匹配 上传,也绝不回退到原始捕获。

共享套件在排空路由并关闭 所属浏览器上下文之前捕获原生测试超时。清理和待处理的测试主体加入同一捕获, 因此后续已关闭页面错误不会替换原始超时证据。

共享失败收集器为渲染器求值和截图捕获 提供一个五秒预算。如果渲染器停滞,它会记录不完整诊断并返回, 以便调用方重新抛出原始失败。迟到的浏览器响应无法在该预算过期后发布截图; 测试操作截止时间以及调用方拥有的浏览器清理保持不变。

私有 JSON 报告的 ci.shardIndex 和 ci.vitestShardCount 字段分别记录 普通 CI 提供的 VITEST_SHARD_INDEX 和 VITEST_SHARD_COUNT。 缺失值保持为 null;手动和独立发布 E2E 调用不会 从 Vitest 的 --shard 参数推断此元数据。

Mantis 为设置日志、捕获尝试及其报告分配一个调用目录; 构建器保留每个尝试的相对路径,并拒绝覆盖现有报告。

仍存在独立的输出所有者,包括 chat-attachment-read-lifecycle。 不要假设未迁移的所有者共享此保留保证。

Chromium 录制期间的截图

会话主机命令状态真实 Gateway 证明使用 page.screenshot({ path }), 不带 clip 或 fullPage: true,保留其现有视口、录制大小、 等待和动画选项。此路径已在 Linux 上使用 Playwright 1.62.1 和完整 Chrome for Testing 151.0.7922.34 验证。

其他录制所有者尚未通过此证明迁移或认证;一些 仍使用定位器或整页截图。这不是整个套件的捕获策略。 在更改其捕获模式之前,验证每个所有者的截图内容和已定稿视频。 当使用已验证的视口路径时,在浏览器外裁剪任何仅元素 PNG。 裁剪无法从已损坏的录制中恢复缺失内容。

在 macOS arm64 复现中,使用 Playwright 1.62.1 及其捆绑的完整 Chrome for Testing 151.0.7922.34,locator.screenshot() 和 page.screenshot({ clip }) 导致小型屏幕录制帧。元素出现在 视频原点,其余为灰色,尽管 PNG、DOM 几何和 功能断言是正确的。fullPage: true 不是一般性变通方法: 大于视口的文档反而可能产生带灰色填充的缩小页面。 未裁剪的视口捕获在相同合成复现中保留了录制;其他浏览器版本和平台需要各自的 验证。

这是上游捕获限制,不是 Gateway 或上下文清理故障。 Chromium 的截图处理器 临时更改共享视图大小并在捕获后恢复;其 屏幕录制生产者可以观察到中间表面。 Playwright 的录制器 用灰色填充尺寸不足的帧。关闭上下文会定稿视频,但 不会修复这些帧。不要过滤掉坏帧或更改 UI 行为 以掩盖此限制。

验证每次捕获周围的已定稿视频内容,而不仅是其尺寸或 定位器断言的成功。对于依赖项升级,使用包含偏移小元素的合成页面复现, 比较元素、裁剪、视口和超大整页截图,并检查每个解码帧。 将真实主机/配置文件录像保留在本地;在共享前检查仅合成内容的公开证明。 正确的 PNG 仍然是有用的静态图像证明,但损坏的视频不是连续流证明。

Gateway 和 E2E

  • Gateway 测试包含在未指定目标的 pnpm test 完整套件中;单独运行它们请使用 pnpm test:gateway。
  • pnpm test:e2e:仓库 E2E 聚合 = pnpm test:e2e:gateway && pnpm test:e2e:agent-plugin-gateway && pnpm test:ui:e2e。
  • pnpm test:e2e:gateway:Gateway 端到端冒烟测试(多实例 WS/HTTP/node 配对)。在 vitest.e2e.config.ts 中默认使用 threads + isolate: false 和一个 worker;使用 OPENCLAW_E2E_WORKERS=<n>(上限为 16)选择并行,并使用 OPENCLAW_E2E_VERBOSE=1 启用详细日志。 大范围运行会准备一次共享运行时,然后使用四个顺序 Vitest 分片在新进程中限制 worker 内存。worker 限制适用于每个进程内部;普通测试失败会被保留,同时剩余分片完成。显式过滤器、监视模式、调用方提供的分片、覆盖率以及报告输出选项保持一次直接调用。
  • pnpm test:live:提供商实时测试(Claude/Minimax/DeepSeek/z.ai 等,由 *.live.test.ts 门控)。需要 API 密钥和 LIVE=1(或 OPENCLAW_LIVE_TEST=1)以取消跳过;使用 OPENCLAW_LIVE_TEST_QUIET=0 输出详细信息。

本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 cl/openclaw