@blazediff/bun
Bun test matcher for visual regression testing with blazediff. Powered by @blazediff/matcher with Bun-specific snapshot state integration.
Features
- Native Bun matcher:
toMatchImageSnapshot()extends Bun's expect - Snapshot state tracking: Bun reports accurate snapshot counts (when API available)
- Multiple comparison algorithms:
core,core-native,ssim,msssim,hitchhikers-ssim,gmsd - Auto-setup: Imports and registers automatically
- Update mode: Works with Bun's
-u/--updateflag - TypeScript support: Full type definitions included
Installation
npm install --dev @blazediff/bun
Peer dependencies: Bun >= 1.0.0
Quick Start
import { expect, it } from 'bun:test';
import '@blazediff/bun';
it('should match screenshot', async () => {
const screenshot = await takeScreenshot();
await expect(screenshot).toMatchImageSnapshot({
method: 'core',
});
});
API Reference
toMatchImageSnapshot(options?)
Bun test matcher for image snapshot comparison.
| Parameter | Type | Description |
|---|---|---|
options |
Partial<MatcherOptions> | Optional comparison options (see below) |
Options
| Option | Type | Default | Description |
|---|---|---|---|
method |
'core' | 'core-native' | 'ssim' | 'msssim' | 'hitchhikers-ssim' | 'gmsd' | 'core' | Comparison algorithm to use |
failureThreshold |
number | 0 | Number of pixels or percentage difference allowed |
failureThresholdType |
'pixel' | 'percent' | 'pixel' | How to interpret failureThreshold |
snapshotsDir |
string | '__snapshots__' | Directory to store snapshots relative to test file |
snapshotIdentifier |
string | 'snapshot' | Identifier for the snapshot file (required for Bun) |
updateSnapshots |
boolean | false | Force update snapshots |
diff |
object | - | Options for core, core-wasm and core-native, such as { threshold: 0.1, antialiasing: true }. ssim and gmsd hold the options of those methods. See @blazediff/matcher |
runInWorker |
boolean | true | Run comparison in worker thread for better performance |
See @blazediff/matcher for full options documentation.
Usage Patterns
Basic Snapshot Test
import { expect, it } from 'bun:test';
import '@blazediff/bun';
it('renders correctly', async () => {
const screenshot = await page.screenshot();
await expect(screenshot).toMatchImageSnapshot({
method: 'core',
snapshotIdentifier: 'homepage',
});
});
Different Comparison Methods
// Fast Rust-native comparison (paths, PNG buffers or raw images)
await expect('/path/to/image.png').toMatchImageSnapshot({
method: 'core-native',
snapshotIdentifier: 'image-core-native',
});
// Pure JavaScript comparison
await expect(imageBuffer).toMatchImageSnapshot({
method: 'core',
snapshotIdentifier: 'image-core',
});
// Perceptual similarity (SSIM)
await expect(imageBuffer).toMatchImageSnapshot({
method: 'ssim',
snapshotIdentifier: 'image-ssim',
});
// Gradient-based comparison
await expect(imageBuffer).toMatchImageSnapshot({
method: 'gmsd',
snapshotIdentifier: 'image-gmsd',
});
Update Snapshots
# Update all snapshots (recommended)
bun test --update-snapshots
# Or using environment variable
BUN_UPDATE_SNAPSHOTS=true bun test
Or programmatically:
await expect(screenshot).toMatchImageSnapshot({
method: 'core',
snapshotIdentifier: 'homepage',
updateSnapshots: true,
});
Custom Thresholds
// Allow up to 100 pixels difference
await expect(screenshot).toMatchImageSnapshot({
method: 'core',
snapshotIdentifier: 'homepage',
failureThreshold: 100,
failureThresholdType: 'pixel',
});
// Allow up to 0.1% difference
await expect(screenshot).toMatchImageSnapshot({
method: 'core',
snapshotIdentifier: 'homepage',
failureThreshold: 0.1,
failureThresholdType: 'percent',
});
Custom Snapshot Directory
await expect(screenshot).toMatchImageSnapshot({
method: 'core',
snapshotIdentifier: 'homepage',
snapshotsDir: '__image_snapshots__',
});
With 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();
});
Negation
// Assert images are different
await expect(screenshot).not.toMatchImageSnapshot({
method: 'core',
snapshotIdentifier: 'different',
});
Serial Tests
For tests that might interfere with each other (e.g., cleaning up snapshots), 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',
});
});
});
Snapshot State Tracking
This matcher attempts to integrate with Bun's snapshot state tracking system. If Bun exposes the snapshot state API to custom matchers, test summaries will show accurate counts:
Snapshots 2 written | 1 updated | 5 passed
Note: Bun's snapshot state API for custom matchers is limited. If snapshot state is unavailable, image snapshots will still work correctly but may not appear in Bun's test summary counts.
Bun-Specific Notes
Snapshot Identifier Required
Unlike Jest and Vitest which can auto-generate snapshot identifiers from test names, Bun has limited context exposure. It's recommended to always provide a snapshotIdentifier:
await expect(screenshot).toMatchImageSnapshot({
method: 'core',
snapshotIdentifier: 'my-component-state', // Recommended
});
Test Path Detection
Bun provides Bun.main which is used to determine the test file path. In some edge cases, you may need to specify snapshotsDir as an absolute path:
await expect(screenshot).toMatchImageSnapshot({
method: 'core',
snapshotIdentifier: 'homepage',
snapshotsDir: '/absolute/path/to/snapshots',
});
Setup
Auto-setup (Recommended)
Simply import the package in your test file:
import '@blazediff/bun';
The matcher is automatically registered when imported.
Manual Setup
Alternatively, call the setup function explicitly:
import { setupBlazediffMatchers } from '@blazediff/bun';
setupBlazediffMatchers();
TypeScript
TypeScript types are included. To use the matcher with TypeScript:
import '@blazediff/bun';
declare module 'bun:test' {
interface Matchers<T = unknown> {
toMatchImageSnapshot(options?: Partial<import('@blazediff/matcher').MatcherOptions>): Promise<MatcherResult>;
}
}
The type augmentation is automatically included when you import the package.
Links
- GitHub Repository
- Documentation
- NPM Package
- @blazediff/matcher - Core matcher logic