Skip to content

chore(ui-scripts,regression-test): ignore whole-pixel shifts in visual regression diffs - #2710

Draft
balzss wants to merge 1 commit into
masterfrom
INSTUI-5180-visual-regression-false-positives
Draft

balzss wants to merge 1 commit into
masterfrom
INSTUI-5180-visual-regression-false-positives

Conversation

@balzss

@balzss balzss commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Summary

  • visual-diff retries the comparison at small integer offsets before calling a screenshot changed, behind --max-shift (default 1, 0 restores exact matching). Scoring over the shared region also covers a screenshot one pixel taller with identical content.
  • viewportHeight 800 → 2000, cutting the fullPage stitching that produces those shifts: 58 stitch operations → 37, and 17/32 → 28/32 pages captured in a single pass (measured against the visual-baselines branch).

A pixel-count tolerance can't do this job. On a real baseline a 1px translation produces 2825 differing pixels and a genuine 40×40 recolour produces 1479 — less than a factor of two apart, so any threshold loose enough to absorb the first would hide the second.

Verified against four real CI baselines — identical, shifted 1px, 1px taller, and a genuine recolour:

--max-shift 0 (current) default
identical ok ok
shifted 1px changed (2825 px) ok
1px taller changed (1280 px) ok
real recolour changed (1479 px) changed

Test Plan

  • Expect a cascade of changed rows on this PR — the viewport change alters layout, so it can't demonstrate its own success. Merging refreshes the baselines.
  • Spot-check a few changed rows in the report to confirm they're the viewport reflow and not something unexpected.

Fixes INSTUI-5180

🤖 Generated with Claude Code

@balzss balzss self-assigned this Sep 7, 2026
@github-actions

github-actions Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor
PR Preview Action v1.8.1

QR code for preview link

🚀 View preview at
https://instructure.design/pr-preview/pr-2710/

Built to branch gh-pages at 2026-09-07 14:56 UTC.
Preview will be ready when the GitHub Pages deployment is complete.

github-actions Bot pushed a commit that referenced this pull request Sep 7, 2026
@github-actions

github-actions Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Visual regression report

Cypress suite: ✅ Passing

Visual diff: ⚠️ Changes detected.

Status Count
Unchanged 93
Changed 3
New 0
Removed 0

Accessibility (axe): ✅ No violations.

📊 View full report — click a screenshot's ⚠ badge to see each violation boxed on the image, with the offending element named and contrast failures shown as color swatches.

Diff images (3)

badge-canvas.png — 1573 pixels differ

tooltip-dark.png — 881 pixels differ

tooltip-light.png — 956 pixels differ

Baselines come from the visual-baselines branch. They refresh on every merge to master. The Cypress suite line covers the a11y and console-error assertions — a ❌ there means the suite found real issues even if the visual diff is clean.

@balzss
balzss requested a review from git-nandor September 7, 2026 09:25
run: npx wait-on http://localhost:3000 --timeout 120000
working-directory: regression-test

# `trashAssetsBeforeRuns` wipes cypress/screenshots at the start of every

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

trashAssetsBeforeRuns -- what is this referencing?

@balzss
balzss removed the request for review from git-nandor September 7, 2026 11:19
@balzss
balzss marked this pull request as draft September 7, 2026 11:21
…l regression diffs

The suite failed on screenshots that were pixel-identical to their baseline but
translated by about a pixel. When a layout box rounds one device pixel
differently the whole painted subtree moves, so a direct comparison lights up
every edge in the image: on a real baseline, a 1px translation produces 2825
differing pixels. That is not a visual regression, and the suite should not
report one.

visual-diff now retries the comparison at small integer offsets before calling a
screenshot changed, behind --max-shift (default 1, 0 restores exact matching).
Scoring happens over the region the two images share, which also covers the
related case of a screenshot one pixel taller with identical content. A
pixel-count tolerance cannot do this job: the shift above and a genuine 40x40
recolour differ by less than a factor of two, so any threshold loose enough to
absorb the first would hide the second.

viewportHeight goes 800 to 2000 to cut the stitching that produces those shifts.
capture: 'fullPage' scrolls the viewport down the document and stitches the
slices, and the stitch is the least reproducible part of the capture. Measured
against the baselines branch, this takes the suite from 58 stitch operations to
37, and from 17 of 32 pages captured in one pass to 28.

The viewport change alters layout, so the first run shows a cascade of changed
rows; merging refreshes the baselines.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@balzss
balzss force-pushed the INSTUI-5180-visual-regression-false-positives branch from 2bbb988 to 29285f7 Compare September 7, 2026 14:52
@balzss balzss changed the title chore(ui-scripts,regression-test,ci): stabilize visual regression capture and tolerate 1px shifts chore(ui-scripts,regression-test): ignore whole-pixel shifts in visual regression diffs Sep 7, 2026
github-actions Bot pushed a commit that referenced this pull request Sep 7, 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.

2 participants