mcpField
R
rendercheck

rendercheck

本地服务
github.com/ParthibanRajasekaran开发工具942 周前更新

关于 rendercheck

RenderCheck 是一个用于前端测试的断言库,基于截图和本地 OCR 检查用户实际看到的文字,而不仅是 DOM 内容。它面向 Playwright、Cypress 及 CI 环境,并提供命令行与 MCP 服务入口。

主要功能

  1. 01在本地通过 Tesseract.js 进行离线 OCR
  2. 02检测文字错误、被遮挡、对比度过低或不可见的情况
  3. 03提供货币与日期的本地化格式断言
  4. 04支持 Playwright 与 Cypress 集成
  5. 05提供命令行工具与 MCP 服务,可在 AI 编码 Agent 中使用

适用场景

  1. 01验证结账页面显示的价格与货币符号是否正确
  2. 02在 CI 中检查文字的对比度与可见性
  3. 03让编码 Agent 在修改界面后验证截图中的文字

MCP 相关

rendercheck mcp 通过 stdio 提供 verify_text 与 read_text 两个工具,MCP 客户端可借此验证截图中的文字是否可见、清晰可读。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"parthibanrajasekaran-rendercheck": {
"command": "npx",
"args": [
"-y",
"@rendercheck/sdk"
]
}
}
}
启动命令npx -y @rendercheck/sdk

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
npm@rendercheck/sdk0.6.0

工具

2

收录的工具列表 · 更新于 2 周前

参数类型必填说明
exactboolean否要求区域中的文本必须与预期文本完全一致
regionobject否仅读取截图的此部分(从左上角开始的像素区域)
region.xnumber是
region.ynumber是
region.widthnumber是
region.heightnumber是
expectedstring是用户应该能够读到的文本
image_pathstring否此计算机上 PNG 或 JPEG 截图的路径
ignore_caseboolean否
image_base64string否Base64 编码的 PNG 或 JPEG;没有文件路径时使用
min_confidencenumber否OCR 置信度,默认值为 80
min_contrast_rationumber否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 }
minConfidence80匹配词语的最低 OCR 置信度(0-100)
minContrastRatio关闭最低 WCAG 对比度,例如 4.5(普通文本)或 3(大号文本)
exactfalse区域中的文本必须与预期文本完全相同,而不只是包含它
ignoreCasefalse除非你这样指定,否则 PAY NOW 不等于 Pay now
domtrue使用 Locator 时,也将文本与元素的 DOM 文本比较
timeout / interval5000 / 250Playwright:重试时长和两次尝试之间的间隔(毫秒)
fullPagefalsePlaywright:捕获整个可滚动页面
lang / langPatheng / 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

链接

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。