tui-tests 是 OpenCode 项目中的一个技能,用于在编写、修复或审查渲染 OpenTUI(testRender、createTestRenderer、createAppFixture)的测试时提供指导,主要面向 packages/tui 和 packages/cli 目录。资料显示,packages/tui 在一个 bun test 进程中运行约 170 个测试文件,CI 在 4 vCPU 运行器上与其他最多两个套件并行执行,Linux 耗时 136-146 秒,Windows 耗时 147-171 秒,大部分时间空闲在帧节奏、生产定时器和睡眠上;多数偶发失败来自等待了错误的信号,然后在繁忙运行器上耗尽帧。
主要能力与核心要点:
-
帧预算不是时间:waitForFrame、waitFor 和 flush 在 maxPasses(默认 20)后放弃;waitForVisualIdle 在 maxFrames(默认 20)后放弃;一次 pass 是一帧。已启动渲染器按 OpenTUI 默认 30 fps 走帧,20 帧约 0.66 秒;生产渲染为 60 fps,所以测试帧比真实应用慢一倍。未启动时 waitFor 和 waitForFrame 在毫秒内失败,错误显示 isRunning: false;同一状态下 flush 和 waitForVisualIdle 立即返回而不等待。
-
只为帧产生的东西等待帧:焦点由定时器设置、Markdown 和代码文本等待 tree-sitter worker、请求和其他状态,应等待信号本身或使用 waitForHighlightedFrame。若测试代码接受 client,可注入 new MockTreeSitterClient({ autoResolveTimeout: 0 })。
-
选择渲染器模式与时钟:组件逻辑用 testRender 不启动,改状态后 await app.renderOnce() 再断言 captureCharFrame();时间驱动的可渲染对象传 clock: new ManualClock(),调用 renderer.pause(),再推进时钟并 renderOnce();整个应用用 createAppFixture,首次使用需约 1 秒空闲导入,重负载下 12-25 秒,仅在行为跨路由或数据时使用;服务端行为用现有 createFetch 和 createEventStream fixture,不要硬编码端口。
-
键盘和鼠标:使用 setup.mockInput 的 pressKey、typeText、pressEnter、pressEscape、pressArrow、pasteBracketedText;渲染器需 kittyKeyboard: true,否则按键映射不同。同一可渲染对象 500ms 内第二次点击会变成选词或选行,应先 clearSelection 或点击至少相隔 2 个单元格。
-
终端尺寸:始终传 width 和 height,否则使用 process.stdout.columns(本地终端或 CI 的 80);覆盖窄和宽宽度,resize 后先 renderOnce 或 flush 再断言;通过计数而非计时衡量工作。
-
定时器、清理和共享状态:耗时超过一秒的测试通常是在等待生产常量,应使其可注入;用 await using 或 finally 清理,先取消定时器再销毁渲染器,最后移除 tmpdir;TestTuiContexts 默认使用固定 /tmp/opencode 路径,涉及写入 paths.state 的 provider 时应传入基于 tmpdir() 的 paths。Bun 不会取消超时测试体。从工作区依赖闭包外的包导入测试辅助函数不会被哈希,可能重放陈旧通过。
-
超时和失败:tui 和 cli 测试脚本使用 bun test --timeout 30000;帧预算失败不是超时问题,调大超时无效,调大 maxPasses 只会掩盖错误等待;在某一分支每次复现的帧预算失败是该变更的回归而非偶发;不要用 skipIf(process.platform === "win32") 隐藏时序偶发,应修复等待。
-
推送前:在 packages/tui 下运行 bun test --timeout 30000 test/<file>,并用 --rerun-each 10 确保全部通过;在另一个套件运行时重复;强制怀疑的竞态(临时放慢定时器或回复)后测试仍须通过;负向控制让谓词不可能,测试须快速失败并输出帧转储而非挂起;检查 Windows 敏感行为。
资料还提到,应阅读根 AGENTS.md 的 Testing 和 TUI Stories 部分(不使用 globalThis mock,从包目录运行),驱动真实 TUI 使用 opencode-dev 技能,CLI 子进程、服务截止时间、Effect TestClock 和 turbo 测试任务使用 unit-tests 技能。
适用场景:在 OpenTUI 渲染的 TUI 或 CLI 测试中编写等待、模拟输入、设置终端尺寸、注入时钟、清理资源及排查偶发失败。限制:资料未提供该技能的安装命令、独立版本、收费信息或平台支持范围;它依赖 OpenCode 仓库内的测试 fixture 和约定,脱离该仓库环境无法直接使用。