{
  "markdown": "# TestivAI Open Source\n\n[![@testivai/witness](https://img.shields.io/npm/v/@testivai/witness.svg?label=%40testivai%2Fwitness)](https://www.npmjs.com/package/@testivai/witness)\n[![@testivai/witness-playwright](https://img.shields.io/npm/v/@testivai/witness-playwright.svg?label=%40testivai%2Fwitness-playwright)](https://www.npmjs.com/package/@testivai/witness-playwright)\n[![@testivai/witness-webdriverio](https://img.shields.io/npm/v/@testivai/witness-webdriverio.svg?label=%40testivai%2Fwitness-webdriverio)](https://www.npmjs.com/package/@testivai/witness-webdriverio)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](./LICENSE)\n\n**Local-first visual regression testing SDKs for modern web applications.**\n\nThis is the home of TestivAI. It contains everything you need to capture, diff, and report visual regressions **fully locally** — MIT-licensed, no account, no server.\n\n> **[See a live report →](https://www.budisugianto.com/testivai-example/)** — a real TestivAI OSS report rendered in your browser, straight from CI. No install, no signup.\n\n[![Real TestivAI report — style-only-change verdict, selector-attributed regions, heatmap diff](./docs/assets/oss-report.png)](https://www.budisugianto.com/testivai-example/)\n\n## Why TestivAI?\n\nPixel-only visual testing drowns you in false positives — a font re-hint or an anti-aliasing shift across machines lights up as a \"change,\" and you spend your time re-approving noise.\n\n**TestivAI pairs every screenshot with a snapshot of the page DOM.** When pixels differ but the DOM is structurally identical, the report flags the diff as **likely render noise** instead of crying wolf. When the DOM actually changed, you see exactly what (`2 added, 1 removed`). That single signal is the difference between a flaky test wall and a report you trust.\n\n- **Fully local, no account** — captures, diffs, and a self-contained HTML report all stay on your machine.\n- **DOM + style-aware noise hint** — separates real changes from render jitter, and catches the stylesheet-only case: identical DOM with changed computed styles reads as \"Styles changed on `button.cta`\", never as noise.\n- **Auditable masks & region-level diffs** — exclude dynamic areas (selectors or coordinates) with the masked region hatched in the diff, and get \"3 changed regions\" with bounding boxes instead of a raw pixel percentage.\n- **Element attribution & exact shift detection** — the report names *which element* changed (\"`div.card:nth-of-type(2)` shifted +8px vertically — content unchanged\") and spots the injected-banner case (\"everything below y=80 moved +24px\"), derived from layout, not pixel guesswork. No local-first tool does this.\n- **First-class adapters** — Playwright (TS/JS **and Python**, Java experimental) and WebdriverIO, using each framework's native APIs; every language shares one set of baselines and one report.\n- **PR-native workflow** — a GitHub Action posts the diff and approves baselines from a `/testivai approve` comment.\n- **No lock-in** — MIT license, baselines live in your git, and `results.json` is a semver-governed public contract.\n\n> **Evaluating this for a team?** [Maintenance & roadmap](docs/maintenance.md)\n> covers who builds it, the release cadence, and what happens to your setup if\n> maintenance ever stops.\n\n> **Already using Playwright's `toHaveScreenshot()`?** It's good, and if a pixel\n> diff answers your question you should keep using it. Here's an honest look at\n> [what TestivAI adds and when it isn't worth the dependency](docs/vs-playwright-builtin.md).\n\n## Eyes for your coding agent\n\nIf an AI agent (Claude Code, Cursor, Copilot, …) writes your UI code, someone still has to check what the UI *looks like* — and it shouldn't be you, one screenshot at a time. TestivAI is built to be that check:\n\n- **No account, no API key, no network** — an agent can run it inside any sandbox without you provisioning secrets.\n- **Machine-readable output** — every run writes `visual-report/results.json` (a [semver-governed schema](./docs/how-it-works.md)) with per-snapshot diff percentages and DOM change summaries, so an agent can read the result and self-correct.\n- **Noise-aware verdicts** — the DOM hint tells the agent whether a pixel diff is *likely render noise* or a *real structural change* (`2 added, 1 removed`), so it doesn't chase anti-aliasing ghosts.\n- **Explanations, bring-your-own-model** — the MCP `explain_snapshot` tool hands your agent layered evidence (which selectors shifted vs changed, whole-page shift detection, style-only changes) and your model writes the narrative: *\"card #2 shifted +24px — likely the banner injected above it.\"* No hosted AI service in the loop.\n- **Human approval stays in the PR** — the agent iterates locally; you approve baselines with one `/testivai approve` comment.\n\nPaste this into your project's `AGENTS.md` / `CLAUDE.md` to wire it up (full guide with MCP setup, a real agent transcript, and the approval rule: [docs/guides/ai-agents.md](./docs/guides/ai-agents.md)):\n\n```markdown\n## Visual verification\nAfter changing any UI code, run `npx playwright test` (TestivAI captures\nscreenshots automatically), then read `visual-report/results.json`.\n- `status: \"changed\"` with `dom.changed: true` → describe the DOM summary and\n  ask whether the change is intended before approving.\n- `status: \"changed\"` with `dom.noiseHint: true` → likely render noise; mention\n  it but don't block.\n- Never run `testivai approve` yourself — baseline approval is a human decision.\n```\n\n## Packages\n\nLive versions are shown by the badges at the top of this README.\n\n| Package | Description |\n|---|---|\n| [`@testivai/witness`](./packages/witness) | Core SDK: CLI, local diffing, baselines, HTML report generator |\n| [`@testivai/witness-playwright`](./packages/playwright) | Playwright reporter/adapter built on top of `@testivai/witness` |\n| [`@testivai/witness-webdriverio`](./packages/webdriverio) | WebdriverIO service + capture function (local mode) |\n| [`@testivai/witness-selenium`](./packages/selenium) | Selenium WebDriver capture adapter (Python/Java Selenium live in `python/` and `java/`) |\n| [`@testivai/mcp`](./packages/mcp) | MCP server — visual results + diff images for AI coding agents |\n| [`testivai` (PyPI)](./python) | Python adapter for playwright-python + pytest plugin — same baselines & report |\n| [`ai.testiv:testivai`](./java) | Java adapter for playwright-java + JUnit 5 extension (experimental) |\n| [`testivai` (RubyGems)](./ruby) | Ruby adapter for Capybara / RSpec / Cucumber — same baselines & report |\n\nPlus:\n- [`action/`](./action) — GitHub Action for PR-based visual approvals\n- [`examples/`](./examples) — minimal real-world example projects\n- [`docs/`](./docs) — public documentation\n- [`e2e/`](./e2e) — OSS smoke E2E test suite\n\n## No test suite? One command.\n\nAI-built and vibe-coded apps (Lovable, Bolt, v0, ...) usually ship with zero\ntests. You still get the full safety net:\n\n```bash\nnpx testivai witness http://localhost:3000\n```\n\nTestivAI launches a headless Chrome, discovers your pages (or takes\n`--pages \"/,/pricing\"`), and captures each one — baselines, diffs, noise\nhints, HTML report, and PR approvals all work exactly as below, no test\nframework required. See the [vibe-coded apps guide](./docs/guides/vibe-coded-apps.md).\n\n## Quick Start (Playwright, Local Mode)\n\n```bash\n# 1. Install\nnpm install -D @testivai/witness-playwright @playwright/test\nnpx playwright install chromium\n```\n\n```jsonc\n// 2. (OPTIONAL) Customize tolerances and report settings.\n// Everything runs locally — no config needed.\n// Only create this file if you want to tune threshold, reportDir, etc.\n// File: .testivai/config.json\n{\n  \"threshold\": 0.1,            // per-pixel color sensitivity (0-1)\n  \"maxDiffPercent\": 0,         // pass diffs at or below this % (your tolerance dial)\n  \"noiseAutoPass\": false,      // true: DOM-identical diffs within noiseMaxDiffPercent pass\n  \"stabilize\": true,           // freeze animations, hide caret, wait for fonts\n  \"ignoreSelectors\": [],       // e.g. [\".live-chat\", \"[data-testid=clock]\"]\n  \"reportDir\": \"visual-report\",\n  \"autoOpen\": false\n}\n```\n\n```ts\n// 3. Wire the reporter — playwright.config.ts\nimport { defineConfig } from '@playwright/test';\n\nexport default defineConfig({\n  reporter: [\n    ['list'],\n    ['@testivai/witness-playwright/reporter'],\n  ],\n});\n```\n\n```ts\n// 4. Add a capture call — tests/example.spec.ts\nimport { test } from '@playwright/test';\nimport { testivai } from '@testivai/witness-playwright';\n\ntest('homepage looks correct', async ({ page }, testInfo) => {\n  await page.goto('http://localhost:3000');\n  await testivai.witness(page, testInfo, 'homepage');\n});\n```\n\n```bash\n# 5. Run\nnpx playwright test\n```\n\n**First run:** baselines are written to `.testivai/baselines/`.\n**Later runs:** screenshots are diffed and a self-contained HTML report is written to `./visual-report/`.\n\n## What you get out of the box (free, no account)\n\n- Full-page screenshot capture via Playwright\n- **Stabilized captures by default** — animations/transitions frozen, caret hidden, web fonts awaited (the top causes of flaky visual tests, neutralized before every screenshot)\n- Local pixel diff with configurable threshold\n- **Tunable pass criteria** — `maxDiffPercent` / `maxDiffPixels` tolerances, plus opt-in `noiseAutoPass` so DOM-identical render noise stops demanding review\n- `ignoreSelectors` for dynamic content (both adapters, global or per-snapshot)\n- Self-contained HTML report (`visual-report/index.html`)\n- Machine-readable results (`visual-report/results.json`)\n- Committed baselines under `.testivai/baselines/` (just `git add` them)\n\n## CI Integration (GitHub Actions)\n\nCopy this single workflow file into your repository. It handles both running the visual regression tests **and** processing `/testivai approve` commands from PR comments — no extra secrets, no external services required.\n\n```yaml\n# .github/workflows/testivai-oss.yml\nname: TestivAI OSS\n\non:\n  pull_request:\n    branches: [main]\n  issue_comment:\n    types: [created]        # listens for /testivai approve commands\n\npermissions:\n  contents: write           # approve action commits updated baselines to the branch\n  pull-requests: write      # post PR diff comment\n  statuses: write           # set pass/fail indicator on the PR\n\njobs:\n\n  # Runs on every PR — captures screenshots, diffs against baselines, posts report\n  visual-regression:\n    name: Visual Regression (OSS)\n    if: github.event_name == 'pull_request'\n    runs-on: ubuntu-latest\n    timeout-minutes: 15\n    steps:\n      - uses: actions/checkout@v4\n      - uses: actions/setup-node@v4\n        with: { node-version: '20', cache: 'npm' }\n      - run: npm ci\n      - run: npx playwright install chromium --with-deps\n      - run: npm run build\n      - run: npm run test:oss          # runs playwright.oss.config.ts\n\n      - name: Post results + upload report\n        uses: testivai/testivai-oss@v1\n        if: always()\n        with:\n          github-token: ${{ secrets.GITHUB_TOKEN }}\n          report-dir: visual-report   # where @testivai/witness writes results.json\n\n  # Runs when a collaborator comments /testivai approve on the PR\n  approve-baselines:\n    name: Approve Baselines\n    if: |\n      github.event_name == 'issue_comment' &&\n      github.event.issue.pull_request != null &&\n      startsWith(github.event.comment.body, '/testivai')\n    runs-on: ubuntu-latest\n    timeout-minutes: 10\n    steps:\n      - uses: testivai/testivai-oss/approve@v1\n        with:\n          github-token: ${{ secrets.GITHUB_TOKEN }}\n          workflow: testivai-oss.yml   # this file's name — used to find the report artifact\n```\n\n### Approve changed baselines\n\nAfter CI posts the diff report on your PR, review the `testivai-visual-report` artifact, then comment:\n\n| Comment | Effect |\n|---|---|\n| `/testivai approve homepage` | Approves one named snapshot |\n| `/testivai approve --all` | Approves every changed snapshot at once |\n\n**What happens:**\n1. Action verifies you have **write** access to the repository (others get a polite rejection)\n2. Downloads the `testivai-visual-report` artifact from the latest CI run on your branch\n3. Copies approved screenshots into `.testivai/baselines/` and commits them to your PR branch\n4. Posts a confirmation comment listing what was approved\n5. CI re-runs automatically — approved snapshots now pass\n\n### What the PR comment looks like\n\n```\nTestivAI Visual Report\n\n4 passed | 2 changed | 1 new — 7 total\n\nChanged Snapshots\n\n▼ homepage — 12.34% different\n  DOM unchanged — pixel diff is likely render noise (font hinting, anti-aliasing).\n\n▼ dashboard — 8.91% different\n  DOM changed — 2 added, 1 removed.\n```\n\n---\n\n## Real-World Example\n\nA complete, minimal consumer project lives at [`testivai-example`](https://github.com/mcbuddy/testivai-example): a static page, three `witness()` calls, the PR `/testivai approve` flow, and a [live report on Pages](https://www.budisugianto.com/testivai-example/) — all against the published packages.\n\n## Repository Layout\n\n```\npackages/\n  witness/     @testivai/witness              — CLI, diff engine, baselines, report\n  playwright/  @testivai/witness-playwright   — Playwright reporter + capture\n  webdriverio/ @testivai/witness-webdriverio  — WebdriverIO service + capture\n  selenium/    @testivai/witness-selenium     — Selenium adapter\n  mcp/         @testivai/mcp                  — MCP server for AI agents\naction/        GitHub Action for PR comments\napprove/       GitHub Action for /testivai approve\nexamples/      framework-specific minimal examples\ndocs/          public documentation (Markdown)\ne2e/           OSS smoke E2E\n```\n\n## Development\n\n```bash\n# Prereqs: Node 20+, pnpm 10+\npnpm install\npnpm build       # tsc all packages\npnpm test        # unit tests across all packages\npnpm e2e         # smoke E2E\npnpm pack:dry    # validate publish artifacts\n```\n\n## Contributing\n\nBug reports, feature requests, and PRs welcome. Please see:\n- [`CONTRIBUTING.md`](./CONTRIBUTING.md)\n- [`CODE_OF_CONDUCT.md`](./CODE_OF_CONDUCT.md)\n- [`.github/ISSUE_TEMPLATE/`](./.github/ISSUE_TEMPLATE/)\n\n## Releases\n\nReleases are published to npm under the `latest` dist-tag, with provenance\nattestations. The flow is Changesets-driven: a PR that changes a published\npackage adds a changeset, merging it opens a \"version packages\" PR collecting\nthe pending bumps, and merging *that* publishes. See\n[`.changeset/README.md`](./.changeset/README.md) for the contributor side and\n[`.github/workflows/release.yml`](./.github/workflows/release.yml) for the\nworkflow itself.\n\n## Attribution\n\nThis repository was extracted from the private TestivAI monorepo with a clean initial git history. Original development history is preserved internally; this public repository is the new source of truth for the SDKs going forward.\n\n## License\n\nMIT — see [LICENSE](./LICENSE).\n",
  "bytes": 14877,
  "sha": "60679a488a14bd96df745a97c62ea703d396d5cfeab4d80991f217869df4117f",
  "repo_slug": "mcbuddy/testivai-oss",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_ai_testiv_mcp_dffa22a5/readme"
}