Skip to content

fix(bridge): fail a missing image snapshot in CI mode instead of writing it - #249

Open
YevheniiKotyrlo wants to merge 2 commits into
callstackincubator:mainfrom
YevheniiKotyrlo:fix/missing-image-snapshot-on-ci
Open

YevheniiKotyrlo wants to merge 2 commits into
callstackincubator:mainfrom
YevheniiKotyrlo:fix/missing-image-snapshot-on-ci

Conversation

@YevheniiKotyrlo

@YevheniiKotyrlo YevheniiKotyrlo commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

What is this?

In Jest's CI mode (--ci, on by default when Jest detects a CI environment), toMatchImageSnapshot now fails when its snapshot does not exist, and saves the received image beside it as <name>-actual.png. Until now it wrote the snapshot and passed on CI too, so a run without committed snapshots compared nothing and a wrong capture could not fail it (#198). With CI=true and no committed snapshots, the playground's web suite passes on main and writes both specs' snapshots; on this branch the two specs fail with:

New snapshot was not written: src/tests/normal/ui/image_snapshots/chromium/out-of-bounds.png does not exist, and missing snapshots are not written in CI mode. Received image saved at src/tests/normal/ui/image_snapshots/chromium/out-of-bounds-actual.png; commit it as src/tests/normal/ui/image_snapshots/chromium/out-of-bounds.png, or run without CI mode (--ci=false) on a machine with this device and commit the snapshot it writes.

How does it work?

The session hands the bridge Jest's updateSnapshot state. When it is "none", CI mode's value, a missing image snapshot is not written and the match fails; outside CI mode, or with --ci=false, it is written as before, and so it is for a createHarnessBridge context that names no state. The received and diff images take the whole snapshot name, so a name holding .png keeps it. Like Jest's own snapshot matchers and jest-image-snapshot, toMatchImageSnapshot now refuses .not, which would turn that failure into a pass. The UI testing guide gets a "Creating snapshots" section and says .not is refused, the CLI reference lists --ci, and the repository ignores the failure images saved beside committed snapshots.

The playground's screenshot and out-of-bounds specs need committed baselines now, so this PR adds the ones CI's Android emulator, iOS simulator and headless Chromium capture. Android's out-of-bounds baseline shows the row's ten squares, which the app draws with one copy of react-native in the bundle, as it has since #227. On my fork, CI's E2E jobs on the current main with this PR pass both specs against these baselines on Android (run) and web (run); GitHub found no macOS runner for the iOS job, which last passed them on 9a505a8 (run).

Why is this useful?

A CI run now fails where it used to pass while comparing nothing: a snapshot that was never committed, or a capture that went wrong, shows up as a failed test with the received image saved for review.

Fixes #198

@vercel

vercel Bot commented Oct 20, 2026

Copy link
Copy Markdown

@YevheniiKotyrlo is attempting to deploy a commit to the Callstack Team on Vercel.

A member of the Team first needs to authorize it.

@YevheniiKotyrlo
YevheniiKotyrlo force-pushed the fix/missing-image-snapshot-on-ci branch from dfeedaf to 41af5b7 Compare October 20, 2026 20:03
@YevheniiKotyrlo
YevheniiKotyrlo marked this pull request as ready for review October 20, 2026 20:50
@YevheniiKotyrlo
YevheniiKotyrlo marked this pull request as draft October 20, 2026 21:28
@YevheniiKotyrlo
YevheniiKotyrlo marked this pull request as ready for review October 21, 2026 17:30
…ing it

In Jest's CI mode, toMatchImageSnapshot fails when its snapshot does not
exist and saves the received image beside it as <name>-actual.png, where it
wrote the snapshot and passed. The Jest session hands the bridge Jest's
updateSnapshot state; a bridge context that names none writes a missing
snapshot as before. The received and diff images take the whole snapshot
name, and toMatchImageSnapshot refuses .not, which would turn the failure
into a pass.

The playground commits the baselines CI's Android emulator, iOS simulator
and Chromium capture for its screenshot and out-of-bounds specs and ignores
the failure images saved beside them. The UI testing guide and the CLI's UI
skill say how snapshots are created in CI mode, and the CLI reference lists
--ci.
# Conflicts:
#	packages/bridge/src/__tests__/image-snapshot.test.ts
#	packages/bridge/src/image-snapshot.ts
#	packages/bridge/src/server.ts
#	packages/runtime/src/expect/matchers/toMatchImageSnapshot.ts
@V3RON
V3RON marked this pull request as draft October 26, 2026 07:11
@V3RON
V3RON marked this pull request as ready for review October 26, 2026 07:11

This branch has not been deployed

No deployments
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.

toMatchImageSnapshot passes when the snapshot is missing, so CI without committed snapshots never compares

2 participants