knock-cli
v1.9.1
Published
Headless replay runner for knock recordings — runs the knock browser extension's actual executor / resolver code under Playwright. Record a flow in the extension, run it in CI byte-for-byte the same.
Maintainers
Readme
knock-cli
运行你用 knock Chrome 扩展录制的浏览器流程 —— 无头、在 CI 里,无需编写任何测试代码。
你只需录制一次流程(在扩展里点击走完你的应用)。knock-cli 会用扩展自己的引擎在 Playwright 下回放它,所以在面板里通过的流程在 CI 里也会通过 —— 逐字节相同的运行。
语言: English · 한국어 · 日本語 · 中文 · Español 文档: knock.racgoo.com/docs/knock-cli
你需要先装 knock 扩展
knock-cli 运行录制 —— 它不创建录制。你用 knock 浏览器扩展(免费)来创建它们,扩展会录制你的点击、输入、网络和存储,并把它们保存为 .knock-test.json 文件。然后 knock-cli 回放这些文件。
获取扩展 → 将 knock 添加到 Chrome
knock extension files in your repo knock-cli
record a flow ─save─▶ ./tests/*.knock-test.json ─run─▶ pass / fail
(clicks + network) (commit to git) (headless, in CI)因为 knock-cli 打包了扩展真正的选择器 + 点击代码,所以不存在第二套需要保持同步的测试套件 —— 录制就是测试。
快速开始
# 1. Install (Node 20+)
npm install --save-dev knock-cli
# 2. Download the browser once (knock-cli ships its own pinned Playwright)
npx knock-cli install-browser
# 3. Record a flow in the knock extension and save it to ./tests
# (Automation tab: Record -> click through your app -> Stop)
# 4. Run it
npx knock-cli ./tests退出码:0 全部通过,1 有东西失败了,2 参数错误或没有可运行的内容 —— 所以它能直接接入任何 CI 流水线。
目录
安装
npm install --save-dev knock-cli # or: pnpm add -D knock-cli / yarn add -D knock-cli然后每台机器下载一次浏览器二进制文件(在 CI 里缓存它):
npx knock-cli install-browser # chromium (default)
npx knock-cli install-browser firefox # or firefox / webkitknock-cli 使用它自己锁定版本的 Playwright,所以全局安装的另一个版本的 Playwright 不算数 —— 始终使用 install-browser。需要 Node.js 20+。
把录制落到磁盘上
有两种方式可以把扩展里的一份录制变成 knock-cli 能运行的文件。
A. 从面板导出。 把一个测试(或一个 Test Set)导出为 .knock-test.json / .knock-test-set.json 文件,并提交到你的仓库。
B. 用 knock-cli serve 连接一个实时文件夹(推荐)。 扩展会把录制直接写入磁盘上的一个文件夹,而且你可以从面板里无头运行它们。录制、编辑、运行全在一处 —— 见下一节。
连接扩展(knock-cli serve)
knock-cli serve 运行一个微型本地服务器,扩展的 Automation → knock-cli 面板会连接到它。一旦连上,面板就直接在磁盘上读写你的录制 —— 每一次录制、编辑和重命名都落进你的仓库,由 git 版本管理。**提交前注意:**录制会保存真实输入值(包括标记为 secret 的字段)以及捕获的 Cookie 和请求体(原因);包含真实凭据的文件请先审查或加入 .gitignore。
npx knock-cli serve ./tests它会打印出一个连接 URL:
knock-cli serve -> http://127.0.0.1:4999/?token=ab12...
Paste this into the knock panel (Automation -> knock-cli) to connect.复制那个 URL,打开扩展的 Automation 标签,把来源切换到 knock-cli,然后粘贴进去。
| 步骤 | 在哪里 | 发生了什么 |
| ------------------------- | --------------------- | ----------------------------------------------------------- |
| knock-cli serve ./tests | 终端 | 启动一个回环服务器,打印出一个 ?token=... URL。 |
| 粘贴 URL | 扩展 → knock-cli 标签 | 面板连接上(重新加载后仍会记住)。 |
| 录制 / 编辑 | 扩展面板 | 录制保存到 ./tests;重命名、移动和配置编辑也会写入。 |
| 运行 | 面板或终端 | 在面板里运行,或者用 npx knock-cli ./tests。引擎完全相同。 |
| 在磁盘上编辑 | 你的编辑器 | 实时同步回面板,反之亦然。 |
服务器只绑定回环地址(127.0.0.1),并且每个请求都需要 URL 里的一次性 token,所以不会有任何东西暴露给你的网络。完整参考:文档 → 扩展集成。
配置
在你的测试旁边放一个 knock-cli.config.json(或者用 --config 指向它)。两个区块都是可选的。CLI 标志始终覆盖配置。
{
"webServer": {
"command": "npm run dev",
"url": "http://localhost:3000",
"reuseExistingServer": true
},
"runner": {
"baseUrl": "http://localhost:3000",
"browser": "chromium",
"viewport": { "width": 1280, "height": 800 },
"workers": 4
}
}通过
knock-cli serve连接了面板?这个文件会在扩展里直接获得一个表单编辑器 —— 无需手改 JSON。
webServer —— 在运行前启动你的应用
如果你的服务器已经在跑,就省略它。否则 knock-cli 会派生该命令,等待 url 响应,运行测试,然后在退出时拆掉服务器。
| 键 | 类型 | 默认值 | 作用 |
| --------------------- | ----------- | ------------ | ------------------------------------------- |
| command | string | required | 开发服务器命令(通过 sh -c 运行)。 |
| url | string | required | 在测试开始前会被轮询,直到它有响应。 |
| timeout | number (ms) | 60000 | 等待 url 的最长时间。 |
| reuseExistingServer | boolean | false | 如果 url 已经有响应,跳过启动。 |
| warmupMs | number (ms) | 0 | 首次响应之后额外的等待(让 SPA 完成预打包)。 |
| env | object | — | 合并到 process.env 之上的额外环境变量。 |
runner —— 每次运行的默认值
每个键都对应一个 CLI 标志(两者都设置时,以标志为准)。
| 键 | 类型 | 默认值 | 作用 |
| ------------------ | ----------------------------- | ---------- | ----------------------------------------------------------- |
| baseUrl | string | 录制自带的 | 覆盖每个录制导航到的源。 |
| browser | chromium firefox webkit | chromium | 引擎。 |
| viewport | { width, height } | 录制自带的 | 强制设定视口(响应式布局)。 |
| workers | number ≥ 1 | 1 | 跨文件的并行 worker 数(同一个 set 内部串行)。 |
| replayNetwork | boolean | true | 提供捕获的响应,而不是访问真实后端。 |
| replayStorage | boolean | true | 重新植入捕获的 cookie + localStorage。 |
| replayViewport | boolean | true | 把窗口大小调整到录制捕获的视口(off = Playwright 默认大小)。 |
| timeout | number (ms) | 10000 | 单步超时。 |
| settleMs | number (ms) | 500 | 步骤之间的网络安静窗口。 |
| settleMaxMs | number (ms) | 30000 | settle 等待的硬上限。 |
| interStepDelayMs | number (ms) | 0 | 步骤之间额外的节奏延迟。 |
| headed | boolean | false | 显示浏览器窗口。 |
CLI 参考
knock-cli <path...> —— 运行(默认)
路径可以是文件(.knock-test.json / .knock-test-set.json)或目录(会被递归遍历)。遍历会跳过点开头的条目和 node_modules —— 与扩展的 Local-folder 文件树相同的规则;显式传入的文件路径始终会被加载。
| 标志 | 默认值 | 说明 |
| --------------------------- | ------------------------- | ----------------------------------- |
| --config <path> | ./knock-cli.config.json | 显式指定配置文件。 |
| --base-url <url> | 录制自带的 | 覆盖每个录制的源。 |
| --viewport <WxH> | 录制自带的 | 强制设定视口,例如 1280x800。 |
| --browser <engine> | chromium | chromium / firefox / webkit。 |
| --workers <n> | 1 | 跨文件的并行 worker 数。 |
| --replay-network on\|off | on | 回放捕获的网络。 |
| --replay-storage on\|off | on | 回放捕获的 cookie / localStorage。 |
| --replay-viewport on\|off | on | 把窗口大小调整到录制的视口。 |
| --headed | off | 显示浏览器窗口。 |
| --timeout <ms> | 10000 | 单步超时。 |
| --settle-ms <ms> | 500 | 步骤间的网络 settle 窗口。 |
| --debug, -v | off | 单步 + 单请求的追踪。 |
| --help, -h | — | 打印帮助。 |
退出码: 0 全部通过 · 1 ≥ 1 个失败 · 2 参数错误 / 未发现任何内容 / web 服务器启动失败。
knock-cli serve [dir] [--port <n>]
服务 dir(默认为 .,不存在则创建)供扩展连接。--port 默认为 4999(0 = 自动挑一个空闲端口)。见连接扩展。
knock-cli impact <pattern...> [paths...]
找出哪些录制调用了某个变更的 API —— 不启动浏览器,不运行。见影响分析。
knock-cli install-browser [names...]
为 knock-cli 锁定版本的 Playwright 下载 Playwright 浏览器二进制文件(默认 chromium)。
影响分析
当你改动一个 API 时,哪些录制的流程触及了它?impact 能在毫秒级回答这个问题,而不运行任何东西 —— 它读取每个录制内部捕获的网络。
# Which tests call /api/orders ?
npx knock-cli impact /api/orders ./tests
# Gate a PR: fail the build until the affected flows are re-recorded
git diff --name-only main | grep routes/ > changed.txt
npx knock-cli impact --api-file changed.txt --fail-on-match ./tests裸路径会匹配任何主机上的该路径;* 是一个 glob 片段;查询参数按子集匹配;--regex 切换为针对完整 URL 的正则表达式。--json 输出机器可读的报告,--fail-on-match 在有任何匹配时退出码为 1。
作为库使用
CLI 所做的一切都被导出:
import { discover, runSingle, runSet } from 'knock-cli';
// discover() 把文件 / 目录路径转成 LoadedTest[] —— 每个 LoadedTest 带有一个
// 解析后的录制 `tests` 数组。
const [loaded] = await discover(['./tests/login.knock-test.json']);
// runSingle 在各自的浏览器上下文里运行一条录制。
const result = await runSingle(loaded.tests[0], {
baseUrl: 'https://staging.example.com',
});
console.log(result.status); // 'passed' | 'failed'
// runSet 让多条录制共享一个上下文运行,每条完成时即时报告。
await runSet(loaded.tests, { replayNetwork: true }, (r) => console.log(r.testName, r.status));故障排查
它在扩展里通过,却在 knock-cli 里失败。 回放引擎是完全相同的,所以差异几乎总是出在环境上 —— 不同的 base URL、一个没有回放相同响应的后端,或者视口不匹配。用 --debug 运行以拿到单步追踪;用 --base-url 和 --viewport 去匹配你录制时的方式。
开发服务器启动了,但 url 一直没有响应。 调高 webServer.timeout,确认 url 确实是该命令实际服务的那个,如果你自己启动服务器就设置 reuseExistingServer: true。
cookie / localStorage 没有被植入。 保持 replayStorage 为开。一个被手工编辑过、格式有误的单个 cookie 会被单独丢弃,而不是让整次运行失败 —— 检查 --debug 追踪。
install-browser 在每次 CI 运行时都重新下载。 在多次运行之间缓存 Playwright 的浏览器目录,或者把 install-browser 作为一个 setup 步骤运行。错误信息会指明它期望的确切版本 + 路径。
链接
- 文档: knock.racgoo.com/docs/knock-cli
- 浏览器扩展(必需): 将 knock 添加到 Chrome
- 源码 / 问题反馈: github.com/racgoo/knock
许可证
MIT © racgoo
