Documentation Menu

Node.js SDK

The RegressionBot Node.js SDK provides a fluent API for integrating visual testing directly into your end-to-end tests (like Playwright or Cypress) or custom scripts.

🔑 Prerequisite: API Key RequiredYou will need an active API key to initialize the SDK connection.
Get API Key →
npm install regressionbot

Basic Usage

Here is a simple example of comparing a preview environment against your production baseline.

import { RegressionBot } from 'regressionbot';

// Automatically uses process.env.REGRESSIONBOT_API_KEY
const client = new RegressionBot();

async function runTest() {
  const job = await client
    .test('https://preview.myapp.com')
    .against('https://myapp.com')
    .forProject('my-web-app')
    .run();

  await job.waitForCompletion();
  const summary = await job.getSummary();

  if (summary.regressionCount > 0) {
    console.log(`Found ${summary.regressionCount} regressions.`);
    process.exit(1);
  }
}

runTest();

Projects & Managed Baselines

A project is a named configuration saved server-side. The first managed-mode run against a new project name creates the config — locking in testOrigin, devices, paths, and masks. Subsequent runs load that config automatically without you needing to re-supply any parameters.

Creating a project (first run)

Supply all parameters on the first run. RegressionBot saves them and captures initial baselines. Pass autoApprove: true to promote those captures to baselines without a manual review step.

import { RegressionBot } from 'regressionbot';

const client = new RegressionBot(process.env.REGRESSIONBOT_API_KEY!);

// First run — creates the project and captures baselines.
const job = await client
  .test('https://staging.myapp.com')
  .forProject('my-billing-app')
  .on(['Desktop Chrome', 'iPhone 12'])
  .paths(['/invoice', '/settings'])
  .autoApprove()        // promote first-run captures to baselines
  .run();

await job.waitForCompletion();
console.log('Baselines saved for project my-billing-app');

Parameter-less reruns (recommended for CI)

Once a project exists, omit .test(), .on(), .check(), and .against(). The SDK loads the saved configuration and starts the job. This is the safest pattern for recurring CI runs — the stored project config is the single source of truth.

import { RegressionBot } from 'regressionbot';

const client = new RegressionBot();

// No origin, devices, or paths — all loaded from the saved project config.
const job = await client
  .forProject('my-billing-app')
  .run();

await job.waitForCompletion();
const summary = await job.getSummary();

if (summary.regressionCount > 0) {
  console.error(`${summary.regressionCount} regression(s) found`);
  process.exit(1);
}

If you supply parameters that differ from the stored config, the API returns a 400 error listing the conflicting fields. To update the project config (for example, to add new pages), delete the project via DELETE /project/{name} and re-run with the new parameters — note that this invalidates existing baselines. See the Project Configurations guide for the full reference.

Advanced Options

You can chain additional methods to customize the devices tested, specific paths, and CSS selectors to mask.

const job = await client
  .test('https://preview.myapp.com')
  .against('https://myapp.com')
  .on(['Desktop Chrome', 'iPhone 13', 'iPad Mini'])
  .check('/')
  .check('/pricing')
  .check('/about')
  .mask(['.ad-banner', '#dynamic-timestamp'])
  .run();

Reading Results

Once a job completes, the summary includes a plain-English RegressionBot Summary of each regression, a perceptual similarity score, and shortened screenshot redirect URLs (e.g. https://screenshots.regressionbot.com/r/{token}) that you can click to view or download the images directly.

const summary = await job.getSummary();

for (const regression of summary.regressions) {
  console.log(`\n${regression.url} [${regression.variantName}]`);
  console.log(`  Changed pixels : ${regression.diffPercentage?.toFixed(2)}%`);
  console.log(`  Visual match   : ${regression.visualMatchScore}/100`);

  if (regression.regressionbotSummary) {
    console.log(`  AI summary     : ${regression.regressionbotSummary}`);
  }

  // Tip: visualMatchScore ≥ 99 + small diffPercentage = likely rendering noise
  const isNoise = (regression.visualMatchScore ?? 0) >= 99 && (regression.diffPercentage ?? 0) < 0.5;
  if (isNoise) {
    console.log('  ⚠️  Possible rendering artifact — review before approving');
  }

  console.log(`  Diff image     : ${regression.diffUrl}`);
}

Use job.downloadResults() to save diff images locally, or { full: true } to also save baseline and current screenshots.

Glob Patterns & Scans

When using the .sitemap() method, you can use .scan() to filter which pages are included using glob patterns.

*

Matches top-level pages only. It skips any nested directory separators (e.g. /docs/api would be skipped).

**

Recursive match (Globstar). Matches everything, including all nested directories and the root path. Recommended for full-site coverage.

// Test every single URL found in the sitemap
const job = await client
  .test('https://preview.myapp.com')
  .sitemap('https://preview.myapp.com/sitemap.xml')
  .scan('**') // Recursive match
  .run();

Test Framework Integrations

Integrate visual regression verification seamlessly into standard Node.js test frameworks to block pulls or PR merges on visual breakage.

Playwright afterAll Hook

Use Playwright's global teardown or suite teardown hook to run visual regression analysis after all end-to-end spec crawls complete successfully.

tests/visual.spec.ts
import { test, expect } from '@playwright/test';
import { RegressionBot } from 'regressionbot';

test.afterAll(async () => {
  console.log('🏁 Tests complete. Running full visual regression suite...');

  const client = new RegressionBot(process.env.REGRESSIONBOT_API_KEY);
  const job = await client
    .test(process.env.PREVIEW_URL || 'https://preview.myapp.com')
    .against('https://myapp.com')
    .on(['Desktop Chrome', 'iPhone 12'])
    .run();

  await job.waitForCompletion();
  const summary = await job.getSummary();

  // Fail the test suite if regressions are flagged
  expect(summary.regressionCount).toBe(0);
});

Jest Visual Snapshot

Run visual regression jobs inside Jest environments, utilizing standard expect wrappers to control test assertions:

__tests__/visual.test.js
const { RegressionBot } = require('regressionbot');

describe('Visual Regression Test', () => {
  it('should have 0 layout regressions on main paths', async () => {
    const client = new RegressionBot();
    const job = await client
      .test('https://staging.myapp.com')
      .against('https://myapp.com')
      .check('/')
      .check('/pricing')
      .run();

    await job.waitForCompletion();
    const summary = await job.getSummary();
    expect(summary.regressionCount).toBe(0);
  }, 60000); // Allow time for headless lambda crawls
});