关于 rendercheck
RenderCheck 是一个用于前端测试的断言库,基于截图和本地 OCR 检查用户实际看到的文字,而不仅是 DOM 内容。它面向 Playwright、Cypress 及 CI 环境,并提供命令行与 MCP 服务入口。
主要功能
- 01在本地通过 Tesseract.js 进行离线 OCR
- 02检测文字错误、被遮挡、对比度过低或不可见的情况
- 03提供货币与日期的本地化格式断言
- 04支持 Playwright 与 Cypress 集成
- 05提供命令行工具与 MCP 服务,可在 AI 编码 Agent 中使用
适用场景
- 01验证结账页面显示的价格与货币符号是否正确
- 02在 CI 中检查文字的对比度与可见性
- 03让编码 Agent 在修改界面后验证截图中的文字
MCP 相关
rendercheck mcp 通过 stdio 提供 verify_text 与 read_text 两个工具,MCP 客户端可借此验证截图中的文字是否可见、清晰可读。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
2收录的工具列表 · 更新于 2 周前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| exact | boolean | 否 | 要求区域中的文本必须与预期文本完全一致 |
| region | object | 否 | 仅读取截图的此部分(从左上角开始的像素区域) |
| region.x | number | 是 | |
| region.y | number | 是 | |
| region.width | number | 是 | |
| region.height | number | 是 | |
| expected | string | 是 | 用户应该能够读到的文本 |
| image_path | string | 否 | 此计算机上 PNG 或 JPEG 截图的路径 |
| ignore_case | boolean | 否 | |
| image_base64 | string | 否 | Base64 编码的 PNG 或 JPEG;没有文件路径时使用 |
| min_confidence | number | 否 | OCR 置信度,默认值为 80 |
| min_contrast_ratio | number | 否 | WCAG 对比度,例如 4.5 |
详细介绍
RenderCheck
断言用户实际看到的内容,而不只是 DOM 中的内容。RenderCheck 会截取屏幕截图,在你的机器上通过 OCR 读取图像;当渲染出的文本有误、淡到难以辨认或完全没有显示时,它会让你的 Playwright 或 Cypress 测试失败,并给出清晰的提示。
已更名。 截至 0.4.1,此软件包以
@freetextfromimage/rendercheck发布。从 0.5.0 起,它的名称为@rendercheck/sdk;API 保持不变。迁移步骤请参阅 CHANGELOG。
- 仅在本地运行。 OCR 在进程内运行(Tesseract.js、WebAssembly)。无需 API 密钥,不会上传,也不会发起网络请求。软件包内附带英语语言数据。
- 捕获 DOM 测试无法发现的问题: 本该显示
$却显示了€、文本被其他元素遮挡、低对比度文本,以及 DOM 中存在但屏幕上没有显示的文本。 - 适用于 CI。 不使用原生模块(纯 JS PNG/JPEG 解码),也不包含浏览器端代码。
Expected to find text "[Total: $14.00]" but OCR read "[Total: €14.00]" (Confidence: 96%)
Diff: Total: [$]14.00 → Total: [€]14.00
安装
npm install --save-dev @rendercheck/sdk
需要 Node 18+,以及 @playwright/test(≥ 1.40)或 cypress(≥ 12)。
Playwright
import { test } from '@playwright/test';
import { expect } from '@rendercheck/sdk/playwright'; // Playwright's expect + toShowText
test('checkout shows the right total', async ({ page }) => {
await page.goto('/checkout');
await expect(page).toShowText('Total: $14.00', {
minConfidence: 85, // OCR confidence of the matched words (default 80)
minContrastRatio: 4.5, // WCAG contrast of the matched words (off unless set)
});
// One element: also compared with its DOM text (innerText).
await expect(page.locator('#total')).toShowText('Total: $14.00');
// Only part of the screenshot (CSS pixels from its top-left corner).
await expect(page).toShowText('Pay now', { region: { x: 120, y: 340, width: 200, height: 40 } });
await expect(page).not.toShowText('Total: €14.00');
});
与 Playwright 自带的断言一样,toShowText 会不断重试,直到通过或 timeout(默认为 5000 ms)耗尽。已经在使用 expect.extend?从相同路径导入 toShowText,然后自行添加即可。
正确显示符合区域设置的价格和日期
await expect(page).toShowCurrency(1234.5, { currency: 'EUR', locale: 'de-DE' }); // expects "1.234,50 €"
await expect(page).toShowDate('2026-03-04', { locale: 'en-GB' }); // expects "04/03/2026"
await expect(page).toShowDate('2026-03-04', { locale: 'en-GB', format: { day: 'numeric', month: 'long', year: 'numeric' } });
预期文本来自 Intl,因此会自动应用各区域设置的分隔符、符号位置和日期顺序。如果屏幕显示的内容不符,失败提示会说明实际显示的内容:
The screen shows USD ($14.00), not GBP (£14.00). 或
The date is formatted for en-US (03/04/2026), but en-GB should show 04/03/2026.
除非你传入 dateTimeZone,否则日期使用 UTC,因此在每台 CI 机器上的结果都相同。
Cypress 提供相同的检查:cy.matchCurrency(1234.5, { currency: 'EUR', locale: 'de-DE' }) 和
cy.matchDate('2026-03-04', { locale: 'en-GB' })。在其他工具中,expectedCurrency 和 expectedDate
(来自软件包根路径)会生成可传给 toShowText 的文本。
从右向左书写的文字及其他文字系统。 每次比较都会忽略方向标记和不换行空格,因此 Intl 输出和 DOM 文本能与 OCR 读取结果匹配。软件包内只附带英语 OCR 数据。对于阿拉伯语、希伯来语、日语等文字,请下载 .traineddata 文件并设置 langPath;系统会根据区域设置选择语言(ar-EG 使用 ara),你也可以自行设置 lang。阿拉伯语区域设置使用阿拉伯-印度数字,因此如果页面显示 14.00,而应显示 ١٤٫٠٠,检查就会失败,这通常正是你想要的结果。
Cypress
// cypress.config.ts
import { defineConfig } from 'cypress';
import { registerRenderCheck } from '@rendercheck/sdk/cypress/plugin';
export default defineConfig({
e2e: { setupNodeEvents(on) { registerRenderCheck(on); } },
});
// cypress/support/e2e.ts
import '@rendercheck/sdk/cypress';
// in a test
cy.visit('/checkout');
cy.matchText('Total: $14.00', { minConfidence: 85, minContrastRatio: 4.5 });
cy.get('#total').matchText('Total: $14.00');
已在真实的 Cypress 环境中测试(13.17、Electron、Linux):
examples/cypress会针对模拟结账页面运行 5 个 spec,其中包括失败用例。其他 Cypress 版本和浏览器未经测试。 运行命令:npm run build && npx cypress@13 run --project examples/cypress(添加--browser electron)。
命令行和 AI Agent
在终端、脚本或 AI 编码 Agent 中检查屏幕截图。使用相同的本地离线 OCR。
npx @rendercheck/sdk verify screenshot.png --expect "Total: $14.00" --min-contrast 4.5
npx @rendercheck/sdk read screenshot.png --json
退出代码 0 表示通过,1 表示断言失败,2 表示发生错误。--json 会输出 { pass, failure, read, confidence, box, message }。
MCP 服务
rendercheck mcp 是一个通过 stdio 通信的 Model Context Protocol 服务,提供两个工具:
verify_text(这段文本真的可见、清晰且易读吗?)和 read_text(用户能看到什么?)。
{
"mcpServers": {
"rendercheck": { "command": "npx", "args": ["-y", "@rendercheck/sdk", "mcp"] }
}
}
Claude Code:claude mcp add rendercheck -- npx -y @rendercheck/sdk mcp。
只需一步,即可为代码库中的每个 Agent 完成设置:
npx @rendercheck/sdk init # Claude Code, Codex/AGENTS.md, Cursor, Copilot
npx @rendercheck/sdk init --agents claude,cursor --dry-run
它会添加一条简短说明(“更改 UI 后,使用 verify_text 验证像素”)和 MCP 服务条目。可以安全地重复运行:只有标记的 RenderCheck 区块会被更新。
运行记录只会保存在你机器上的 ~/.rendercheck/usage.jsonl 中,因此 rendercheck stats 可以向你显示这些记录。屏幕截图文本绝不会被记录,也不会发送到任何地方。设置 RENDERCHECK_NO_USAGE_LOG=1 即可关闭此功能。
核心
import { verifyText } from '@rendercheck/sdk/core';
const report = await verifyText({
image: fs.readFileSync('screenshot.png'), // PNG or JPEG
expected: 'Total: $14.00',
options: { minContrastRatio: 4.5 },
});
if (!report.pass) console.error(report.message);
recognize(image, { region }) 返回原始 OCR 结果(words、lines、以图像像素为单位的框),而
analyzeWordContrast 提供 WCAG 对比度计算,方便你构建自己的断言。
选项
| 选项 | 默认值 | |
|---|---|---|
region | 整个屏幕截图 | 屏幕截图像素中的 { x, y, width, height } |
minConfidence | 80 | 匹配词语的最低 OCR 置信度(0-100) |
minContrastRatio | 关闭 | 最低 WCAG 对比度,例如 4.5(普通文本)或 3(大号文本) |
exact | false | 区域中的文本必须与预期文本完全相同,而不只是包含它 |
ignoreCase | false | 除非你这样指定,否则 PAY NOW 不等于 Pay now |
dom | true | 使用 Locator 时,也将文本与元素的 DOM 文本比较 |
timeout / interval | 5000 / 250 | Playwright:重试时长和两次尝试之间的间隔(毫秒) |
fullPage | false | Playwright:捕获整个可滚动页面 |
lang / langPath | eng / bundled | 其他 Tesseract 语言:将 langPath 指向包含 <lang>.traineddata.gz 的文件夹 |
拉取请求注释(GitHub Actions)
断言失败时,RenderCheck 可以为 CI 留下记录:一个 JSON 文件,以及一份用红色框出失败文本的屏幕截图副本。action/ 中的 GitHub Action 会将这些内容转换为失败测试所在行的拉取请求注释(“Expected Total: $14.00, OCR read Total: €14.00, failing region x=140, y=244, 219×24 px”)、作业摘要表,以及包含标注截图的可下载报告。
env:
RENDERCHECK_REPORT_DIR: rendercheck-report # on GitHub Actions this is already the default
steps:
- run: npx playwright test # or cypress run
- uses: ParthibanRajasekaran/text-from-image/packages/rendercheck/action@<ref>
if: always()
在 GitHub Actions 之外,记录功能默认关闭;除非你设置 RENDERCHECK_REPORT_DIR(将其设为空字符串即可在此处关闭记录)。失败只会在最后一次重试后记录一次;如果重试通过,则会移除该记录。
GitHub 注释关联到源代码行,而不是屏幕坐标,因此区域信息会写在消息中,并绘制在屏幕截图上。一切都在你的工作流中完成:无需服务、令牌或网络请求。
能做什么,不能做什么
- OCR 并非完美。 它可能会混淆
l/I/1和O/0,也可能漏掉文本。在繁杂页面上,彩色背景上的浅色文本经常会被漏识别:请将断言限定到元素(page.locator('#pay'))或某个region。非常淡的文本恰恰是对比度检查要查找的内容,可能完全无法识别。此时断言仍会失败,并报告“在 DOM 中,但在渲染像素中不可见”。 - 对比度是根据像素测量的(通过 k-means 比较文本颜色与周围颜色),而不是根据 CSS 测量。渐变、文字后方的图像以及抗锯齿都会导致测量结果只是估算值。
- 它会验证可见文本。它不会检查布局、间距或对比度以外的颜色;请将它与视觉回归工具配合使用,而非用它取代视觉回归工具。
- 开箱即用时仅支持英语。
网络
此程序包中的代码不会发起网络请求。Tesseract 自身的缓存也已关闭,因此项目中不会写入任何内容。(失败记录是唯一的例外,并且只有在你启用时才会生成:见上文。)要在 Linux 上自行验证:npm run test:offline 会在无网络命名空间(unshare -rn)中运行测试。
示例
examples/playwright/ 是一个针对模拟结账页面(本地 HTML 文件)的 Playwright 测试套件,其中包含失败案例:货币错误、对比度过低、文本被另一个元素遮挡。
npx playwright install chromium # once
npm run test:example
examples/github-actions.yml 展示了如何在 CI 中使用它。
许可证
MIT
链接
- 文档:https://getrendercheck.com/developers
- 它如何保持本地运行(架构和威胁模型):https://getrendercheck.com/security
- 问题和功能请求:https://github.com/ParthibanRajasekaran/text-from-image/issues
- 安全问题报告:参见 SECURITY.md
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。