Snapvisor Docs

Migrate from Cypress image snapshot plugins

Move a Cypress suite from cypress-image-snapshot or cypress-visual-regression to Snapvisor - how cy.matchImageSnapshot and cy.compareSnapshot, committed snapshot folders, thresholds and update flags translate to cy.argosScreenshot.

This guide moves a Cypress suite that uses cy.matchImageSnapshot() (from cypress-image-snapshot or its maintained fork @simonsmith/cypress-image-snapshot) or cy.compareSnapshot() (from cypress-visual-regression) to Snapvisor. You keep your tests and your CI. What changes is the capture command, and where baselines and review live.

It was written against @snapvisor/cypress 8.0.0, @simonsmith/cypress-image-snapshot 11.0.0, cypress-image-snapshot 4.0.1 and cypress-visual-regression 6.0.1. Option names and flags differ between plugin versions, so check the README of the version you run.

The one change that matters

Both plugins compare a screenshot with a baseline image kept in your repository, and a failed comparison fails the test. cypress-image-snapshot stores snapshots under cypress/snapshots by default, and the diff images next to them. cypress-visual-regression keeps base, actual and diff folders, and you choose between creating the base images and comparing against them with its visualRegressionType setting (base or regression).

Snapvisor stores baselines server-side, per reference branch. cy.argosScreenshot captures the screenshot, your pipeline uploads it, and Snapvisor compares it with the approved screenshot for the branch. A changed screenshot does not fail the test. You approve it in the review UI, and it becomes the new baseline for that branch. See Baseline builds.

Your committed snapshots do not carry over, and there is no import path. Your first Snapvisor build on your base branch becomes the baseline. Plan the switch for a moment when your base branch is visually correct.

Concept mapping

Cypress pluginsSnapvisor equivalent
cy.matchImageSnapshot("name") or cy.compareSnapshot("name")cy.argosScreenshot("name") from @snapvisor/cypress. The name is required and must be unique within a run.
cy.get(".card").matchImageSnapshot()cy.get(".card").argosScreenshot("card")
Snapshot folders in git (cypress/snapshots, or base and diff folders)Nothing in your repository. Baselines live on the server.
customSnapshotsDir, customDiffDir, visualRegressionBaseDirectory, visualRegressionDiffDirectoryNot needed. There are no baseline or diff files to place.
--env updateSnapshots=true (older versions) or --expose updateSnapshots=true (current @simonsmith version)Approve the change in the review UI. See Review workflow.
A base run to create baselines and a regression run to compare (visualRegressionType)One kind of run. The first build on your base branch is the baseline; later builds are compared with it.
failureThreshold, failureThresholdType, errorThresholdthreshold. See Tolerances.
capture: "viewport" or "fullPage"The same Cypress capture option. Snapvisor captures the full page unless you pass capture: "viewport".
blackout: [".selector"]The same Cypress blackout option. Passing blackout replaces the default [data-visual-test="blackout"]; include it in your array to keep it. See Masks and animations.
failOnSnapshotDiff=false, failSilentlyAlready the behavior. A changed screenshot does not fail the test.
requireSnapshots=trueNot needed. A build with no baseline yet is simply the first one.
A failed assertion in the Cypress reportA change flagged in the Snapvisor review and on the pull request status check.

Swap the command

Install the SDK:

npm install --save-dev @snapvisor/cypress

Register the task in your Cypress config, which uploads the screenshots when the run ends:

// cypress.config.ts
import { defineConfig } from "cypress";
import { registerArgosTask } from "@snapvisor/cypress/task";

export default defineConfig({
  e2e: {
    setupNodeEvents(on, config) {
      registerArgosTask(on, config, {
        // Upload only on CI. The default is to upload.
        uploadToArgos: !!process.env.CI,
      });
      return config;
    },
  },
});

Import the command in your support file, in place of the plugin's command registration:

 // cypress/support/e2e.ts
-import { addMatchImageSnapshotCommand } from "@simonsmith/cypress-image-snapshot/command";
-addMatchImageSnapshotCommand({ failureThreshold: 0.2 });
+import "@snapvisor/cypress/support";

Then change the calls in your specs:

 // cypress/e2e/login.cy.ts
 describe("Login", () => {
   it("is publicly accessible", () => {
     cy.visit("/login");
-    cy.matchImageSnapshot("login", { blackout: [".timestamp"] });
+    cy.argosScreenshot("login", { blackout: [".timestamp"] });
   });
 });

Remove the plugin's own setupNodeEvents registration (addMatchImageSnapshotPlugin(on, config) in cypress-image-snapshot 4.0.1, addMatchImageSnapshotPlugin(on) in the @simonsmith fork, or configureVisualRegression(on)) in the same change. Keep Cypress's other assertions; only the screenshot call changes.

cy.argosScreenshot takes Cypress's own cy.screenshot() options, so capture, blackout, clip and disableTimersAndAnimations work as they do in Cypress. It also stabilizes the page before capturing. It waits for web fonts, images and aria-busy regions to settle, hides carets and scrollbars and normalizes font anti-aliasing. It is on by default; pass stabilize: false to turn it off. See Flaky test detection for how recurring changes are handled.

To capture several sizes in one call, pass viewports:

cy.argosScreenshot("home", {
  viewports: ["iphone-6", { width: 1280, height: 800 }],
});

Tolerances

cypress-image-snapshot takes failureThreshold together with failureThresholdType, which is either a pixel count or a percent of the image. cypress-visual-regression takes errorThreshold, a limit on how much of the image may differ. Each is an allowance for how much of the image may differ before the test fails.

Snapvisor has one setting, threshold, a sensitivity between 0 and 1 that defaults to 0.5. Higher means less sensitive. It is a different kind of setting from the plugin options above, so do not copy a number across:

cy.argosScreenshot("chart", { threshold: 0.7 });

Start from the default and adjust only when a specific screenshot is noisy. If you raised a failure threshold to absorb font or anti-aliasing differences between machines, remove it and try the default first. A change is flagged for review, not failed, so a small difference is a decision for a reviewer and not a red build.

Masks and animations

Full page. Cypress captures the full page by default, and cy.argosScreenshot does the same. For a viewport-sized capture, pass capture: "viewport":

cy.argosScreenshot("home", { capture: "viewport" });

Animations. cy.argosScreenshot leaves Cypress's own disableTimersAndAnimations setting alone, and Cypress disables timers and CSS animations during screenshots by default. Pass disableTimersAndAnimations: false to let them run.

Blackout. By default, elements matching [data-visual-test="blackout"] are blacked out. Passing your own blackout replaces that default, so include [data-visual-test="blackout"] in your array if you rely on it:

cy.argosScreenshot("dashboard", {
  blackout: [
    '[data-visual-test="blackout"]',
    ".clock",
    "[data-testid=avatar]",
  ],
});

A blacked-out area is covered in the screenshot, so changes inside it are not compared. Use it for clocks, ads and random data rather than raising the threshold.

Delete the snapshot files

Once builds are landing in Snapvisor and the check is required:

  1. Delete the snapshot folders from the repository, and from Git LFS if you stored them there: cypress/snapshots and its __diff_output__ folders, or the base, actual and diff folders, or whatever customSnapshotsDir and the visualRegression*Directory settings point to.
  2. Remove the .gitignore rules that only existed for diff or actual images.
  3. Remove --env updateSnapshots=true, --expose updateSnapshots=true, requireSnapshots, failOnSnapshotDiff, visualRegressionType, visualRegressionUpdateSnapshots and visualRegressionGenerateDiff from package.json scripts, docs and CI. Accepting a change now happens in the review UI, and no step rewrites files and commits them.
  4. Remove the plugin's registration from cypress.config and the support file, and uninstall the plugin.
  5. Remove any CI job that only existed to regenerate baselines on a reference machine or container, and the base-creation run if you used cypress-visual-regression.

Your pull requests stop carrying binary image changes. Reviewers see the before and after in the review UI instead.

The CI change

Before, the job ran the tests, and a changed screenshot failed the job:

- run: npm ci
- run: npx cypress run

After, the job also has the project token. A changed screenshot no longer fails the job:

- run: npm ci
- run: npx cypress run # captures via cy.argosScreenshot, uploads when the run ends
  env:
    ARGOS_TOKEN: ${{ secrets.ARGOS_TOKEN }}

Copy the project token from your project's settings in the app, and store it as a CI secret, never in the repository. See Access tokens. On GitHub Actions you can drop the secret with tokenless authentication. More workflows, including merge queues and fork pull requests, are in GitHub Actions recipes.

Run both side by side

You do not have to switch in one pull request. Keep the plugin calls and add cy.argosScreenshot next to them:

cy.matchImageSnapshot("login");
cy.argosScreenshot("login");

A way to run the overlap:

  1. Add the Snapvisor task, the support import and the calls, and merge them to your base branch so the first Snapvisor build becomes the baseline. Both commands can be registered at once.
  2. Keep the plugin assertions as your gate, and the Snapvisor check optional, while you compare results.
  3. When the Snapvisor builds match your expectations on a few pull requests, make the Snapvisor check required, then remove the plugin calls and snapshot files.

Make the Snapvisor check the gate

The upload step finishes once the build has been created, whether or not it contains changes. A failed upload (bad token, unresolvable commit, network) is an error. The review gate is the commit status check Snapvisor posts to the pull request, which asks for review until someone approves or rejects the changes.

If the check is optional, nothing blocks a merge. A green test job means the screenshots arrived, not that they are unchanged. Require the check in branch protection — see GitHub or GitLab.

First-build checklist

After the first Snapvisor build on your base branch:

  1. Open the build and confirm it has a screenshot for each snapshot call you replaced.
  2. Look through the screenshots for fonts, images and animations that did not settle. Fix those first, before any threshold change.
  3. Run the same build twice on one commit and check that nothing shows as changed.
  4. Open a pull request with one small visual change. Confirm the Snapvisor status check appears, asks for review, and clears after you approve.
  5. Make the Snapvisor check required in branch protection.

Frequently asked questions

Do I have to stop using Cypress?
No. Snapvisor captures through your Cypress tests. Cypress stays your test runner, and you keep your specs, commands and config.
Can I import my committed snapshot images as baselines?
No. There is no import path. Your first Snapvisor build on your base branch becomes the new baseline: it has nothing to compare against, so it is approved automatically. Run it when your base branch is visually correct.
Does cy.argosScreenshot fail the test when the screenshot changes?
No. The test passes once the screenshot is captured. The review gate is the commit status check Snapvisor posts to the pull request, which asks for review until someone approves or rejects the changes. Make that check required in branch protection.
Can I run the snapshot plugin and Snapvisor side by side while I switch?
Yes. They are independent. Keep your existing matchImageSnapshot or compareSnapshot calls, add cy.argosScreenshot calls next to them, and remove the plugin once the Snapvisor check is your gate.

On this page