Skip to content

Replace resemble.js with pixelmatch as the comparison engine#1151

Draft
wswebcreation wants to merge 10 commits into
mainfrom
ws/investigate-flakiness
Draft

Replace resemble.js with pixelmatch as the comparison engine#1151
wswebcreation wants to merge 10 commits into
mainfrom
ws/investigate-flakiness

Conversation

@wswebcreation
Copy link
Copy Markdown
Member

@wswebcreation wswebcreation commented Jun 3, 2026

Why

Users have been seeing flaky visual tests caused by minor rendering differences that are invisible to the human eye, things like sub-pixel font hinting, 1px anti-aliasing variations at element edges, and slight shadow rendering changes between test runs. These aren't real regressions, but they cause tests to fail intermittently, which erodes confidence in the visual test suite.

The root cause is that the current resemble.js engine compares images using per-channel RGB tolerance. RGB is not a perceptually uniform colour space, so a tolerance of 32/255 on the red channel has a completely different visual meaning than the same tolerance on the blue channel. It also has a large-image sampling optimisation that silently skips about 31% of pixels (every 6th row and column) on full-page screenshots, including the entire first row.

pixelmatch, compares images in the YIQ colour space. The weights in that space reflect how sensitive the human eye actually is: luminance matters most, then the orange-blue axis, then the purple-green axis. Its anti-aliasing detector cross-validates against both images at once, so it only skips a pixel if both the baseline and the actual look like an anti-aliased edge there. The net result is that invisible rendering noise passes, and real regressions don't.

What changed

A compareEngine option has been added to the service configuration. Setting it to 'pixelmatch' routes comparisons through the new adapter; 'resemble' (the default) keeps the existing behaviour unchanged.

// wdio.conf.ts
services: [
    ['visual', {
        compareEngine: 'pixelmatch',
        // ...rest of config
    }]
]

The pixelmatch adapter has the same interface as the resemble adapter, so all downstream behaviour, diff images, JSON reports, diffPixels bounding boxes, mismatch percentages works identically regardless of which engine is used.

A few bugs were found and fixed in the process:

  • Top-row artifact on full-page screenshots: Jimp's contain() was being used to normalise images to the same canvas size. contain() centers the image, which shifts content by 1px and creates a false diff across the top row. Replaced with buffer-level padding that anchors content at (0,0).
  • Ignored region 1px under-coverage: The device-pixel size of an ignored element region was computed using Math.floor, which can lose a pixel when cssSize × DPR has a fractional part. Changed to Math.ceil for width and height so the full element area is always covered.

Notes

The compareEngine option is marked beta. The resemble engine remains the default and nothing changes for existing users unless they explicitly opt in. It might be that we will remove it when we release it as a large breaking change.

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Jun 3, 2026

⚠️ No Changeset found

Latest commit: 0447981

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@wswebcreation wswebcreation changed the title Ws/investigate flakiness Replace resemble.js with pixelmatch as the comparison engine Jun 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant