Skip to Content
Documentation@blazediff/bun

@blazediff/bun

Bun test matcher for visual regression testing with blazediff. Provides native toMatchImageSnapshot() matcher with automatic snapshot state tracking and support for multiple comparison algorithms.

Installation

npm install --save-dev @blazediff/bun

Peer dependencies: Bun >= 1.0.0

Features

  • Native Bun matcher: toMatchImageSnapshot() extends Bun’s expect API
  • Snapshot state tracking: Integrates with Bun’s snapshot system (when API available)
  • Multiple algorithms: Choose from 6 comparison methods
  • Auto-setup: Imports and registers automatically
  • Update mode: Works with Bun’s -u/--update flag
  • Full TypeScript support: Complete type definitions included

Quick Start

import { expect, it } from 'bun:test'; import '@blazediff/bun'; it('should match screenshot', async () => { const screenshot = await page.screenshot(); await expect(screenshot).toMatchImageSnapshot({ method: 'core', snapshotIdentifier: 'homepage', }); });

The matcher auto-registers when you import @blazediff/bun. No additional setup required!

Unlike Jest/Vitest, Bun has limited context exposure. Always provide a snapshotIdentifier for reliable snapshot management.

API Reference

toMatchImageSnapshot(options?)

Bun test matcher for image snapshot comparison.

await expect(imageInput).toMatchImageSnapshot(options?);

Parameters

ParameterTypeDescription
imageInputImageInputImage to compare (file path or buffer with dimensions)
optionsPartial<MatcherOptions>Optional comparison options

Options

OptionTypeDefaultDescription
methodComparisonMethod'core'Comparison algorithm
snapshotIdentifierstring'snapshot'Required: Snapshot filename identifier
failureThresholdnumber0Allowed difference (pixels or percentage)
failureThresholdType'pixel' | 'percent''pixel'Threshold interpretation
snapshotsDirstring'__snapshots__'Snapshot directory (relative to test)
updateSnapshotsbooleanfalseForce snapshot update
thresholdnumber0.1Color threshold for core/bin (0-1)

See @blazediff/matcher for all available options.

Comparison Methods

core - Pure JavaScript (Default)

await expect(screenshot).toMatchImageSnapshot({ method: 'core', snapshotIdentifier: 'my-test', });

bin - Rust Native (Fastest)

await expect('/path/to/image.png').toMatchImageSnapshot({ method: 'bin', snapshotIdentifier: 'my-test', });

ssim - Perceptual Similarity

await expect(screenshot).toMatchImageSnapshot({ method: 'ssim', snapshotIdentifier: 'my-test', });

gmsd - Gradient-based

await expect(screenshot).toMatchImageSnapshot({ method: 'gmsd', snapshotIdentifier: 'my-test', });

Usage Patterns

Basic Snapshot Test

import { expect, it } from 'bun:test'; import '@blazediff/bun'; it('renders homepage correctly', async () => { const screenshot = await browser.screenshot(); await expect(screenshot).toMatchImageSnapshot({ method: 'core', snapshotIdentifier: 'homepage', }); });

Custom Thresholds

Allow small differences while catching regressions:

// Allow up to 100 pixels difference await expect(screenshot).toMatchImageSnapshot({ method: 'core', snapshotIdentifier: 'homepage', failureThreshold: 100, failureThresholdType: 'pixel', }); // Allow up to 0.5% difference await expect(screenshot).toMatchImageSnapshot({ method: 'core', snapshotIdentifier: 'homepage', failureThreshold: 0.5, failureThresholdType: 'percent', });

Use percentage-based thresholds for responsive images that may change size across different viewports.

Update Snapshots

# Update all failing snapshots (recommended) bun test --update-snapshots # Using environment variable BUN_UPDATE_SNAPSHOTS=true bun test

The Bun’s --update-snapshots flag is consumed by Bun internally and won’t update image snapshots.

Programmatically:

await expect(screenshot).toMatchImageSnapshot({ method: 'core', snapshotIdentifier: 'homepage', updateSnapshots: true, });

Custom Snapshot Directory

await expect(screenshot).toMatchImageSnapshot({ method: 'core', snapshotIdentifier: 'homepage', snapshotsDir: '__image_snapshots__', });

Descriptive Identifiers

Use descriptive identifiers to organize snapshots:

// By viewport await expect(screenshot).toMatchImageSnapshot({ method: 'core', snapshotIdentifier: 'homepage-mobile-375', }); await expect(screenshot).toMatchImageSnapshot({ method: 'core', snapshotIdentifier: 'homepage-desktop-1920', }); // By state await expect(screenshot).toMatchImageSnapshot({ method: 'core', snapshotIdentifier: 'button-hover-state', }); // By theme await expect(screenshot).toMatchImageSnapshot({ method: 'core', snapshotIdentifier: 'dashboard-dark-theme', });

Negation

Test that images are intentionally different:

const before = await page.screenshot(); await page.click('.toggle-theme'); const after = await page.screenshot(); // Assert that theme toggle changed the UI await expect(after).not.toMatchImageSnapshot({ method: 'core', snapshotIdentifier: 'before-theme-toggle', });

Serial Tests

For tests that share state, use serial execution:

import { describe, it } from 'bun:test'; describe.serial('Visual regression tests', () => { it('test 1', async () => { await expect(image1).toMatchImageSnapshot({ method: 'core', snapshotIdentifier: 'test-1', }); }); it('test 2', async () => { await expect(image2).toMatchImageSnapshot({ method: 'core', snapshotIdentifier: 'test-2', }); }); });

Integrations

Playwright

import { test, expect } from 'bun:test'; import '@blazediff/bun'; import { chromium } from 'playwright'; test('visual regression with Playwright', async () => { const browser = await chromium.launch(); const page = await browser.newPage(); await page.goto('https://example.com'); const screenshot = await page.screenshot(); await expect(screenshot).toMatchImageSnapshot({ method: 'core', snapshotIdentifier: 'homepage', }); await browser.close(); });

Puppeteer

import { test, expect } from 'bun:test'; import '@blazediff/bun'; import puppeteer from 'puppeteer'; test('captures homepage', async () => { const browser = await puppeteer.launch(); const page = await browser.newPage(); await page.goto('https://example.com'); const screenshot = await page.screenshot({ fullPage: true }); await expect(screenshot).toMatchImageSnapshot({ method: 'core', snapshotIdentifier: 'homepage-full', }); await browser.close(); });

Snapshot State Tracking

The matcher attempts to integrate with Bun’s snapshot state system. If Bun exposes the snapshot state API, test summaries will show accurate counts.

Note: Bun’s snapshot state API for custom matchers is currently limited. Image snapshots will work correctly but may not appear in Bun’s test summary counts.

TypeScript

Full TypeScript support is included:

import { expect, it } from 'bun:test'; import '@blazediff/bun'; // Types are automatically augmented it('typed test', async () => { const screenshot: Buffer = await takeScreenshot(); await expect(screenshot).toMatchImageSnapshot({ method: 'core', snapshotIdentifier: 'my-test', failureThreshold: 0.1, failureThresholdType: 'percent', }); });

The type augmentation is automatic when you import the package.

Configuration

Default Options

Create a wrapper to set default options:

// test-utils.ts import { expect } from 'bun:test'; import type { MatcherOptions } from '@blazediff/matcher'; export async function expectImageSnapshot( image: any, identifier: string, options?: Partial<MatcherOptions> ) { return expect(image).toMatchImageSnapshot({ method: 'core', failureThreshold: 0.1, failureThresholdType: 'percent', snapshotIdentifier: identifier, ...options, }); }
// test.spec.ts import { expectImageSnapshot } from './test-utils'; it('uses default options', async () => { await expectImageSnapshot(screenshot, 'homepage'); });

Bun-Specific Notes

Always Use Snapshot Identifiers

Unlike Jest and Vitest, Bun has limited test context exposure. Always provide a snapshotIdentifier:

// ✓ Good await expect(screenshot).toMatchImageSnapshot({ method: 'core', snapshotIdentifier: 'my-component', }); // ✗ Avoid - falls back to generic "snapshot" await expect(screenshot).toMatchImageSnapshot({ method: 'core', });

Test Path Detection

The matcher uses Bun.main to determine the test file path. In edge cases, specify an absolute snapshotsDir:

await expect(screenshot).toMatchImageSnapshot({ method: 'core', snapshotIdentifier: 'homepage', snapshotsDir: '/absolute/path/to/snapshots', });

Performance

Bun’s native speed complements blazediff’s performance. For maximum speed, use the bin method with file paths:

// Fastest combination: Bun + Rust native await expect('/path/to/image.png').toMatchImageSnapshot({ method: 'bin', snapshotIdentifier: 'fast-test', });

Troubleshooting

Snapshots Not Updating

Ensure you’re using the -u or --update flag:

bun test -u

Or set updateSnapshots: true in options.

Type Errors

Make sure @blazediff/bun is imported:

import '@blazediff/bun';

Snapshot Directory Not Found

The matcher creates directories automatically. If you see errors, check file permissions or specify an absolute path:

await expect(screenshot).toMatchImageSnapshot({ method: 'core', snapshotIdentifier: 'test', snapshotsDir: '/absolute/path/to/snapshots', });
Last updated on