QA How-To
How to Use Cypress visual testing (2026)
Build reliable cypress visual testing in 2026 with Percy setup, stable snapshots, responsive coverage, CI review, baseline governance, and clear debugging.
26 min read | 3,435 words
TL;DR
Cypress visual testing uses Cypress to reach a controlled UI state and a visual tool to compare that state with an approved baseline. Start with high-value components, stabilize every changing input, capture named snapshots through a documented integration such as Percy, and require deliberate diff review in CI.
Key Takeaways
- Cypress drives the application state, while a visual integration captures, compares, stores, and reviews snapshots.
- Choose local pixel comparison for infrastructure control or a managed service for cross-browser rendering and team review.
- Stabilize data, time, viewport, fonts, animation, and loading state before capturing any snapshot.
- Prefer focused component or region snapshots, with a smaller set of intentional full-page checkpoints.
- Treat baseline approval as code review, with ownership and evidence for every accepted change.
- Run visual checks in a pinned environment and keep the visual job's pass or fail status visible in pull requests.
- Combine visual checks with functional and accessibility assertions because images cannot prove behavior or semantics.
Cypress visual testing catches visible regressions that functional assertions often miss, such as clipped labels, overlapping controls, missing icons, font fallback, and broken responsive layout. Cypress drives the browser into the required state, while a visual integration captures and compares the rendered result with an approved baseline.
Cypress itself does not perform image comparison. Its built-in cy.screenshot() command captures an image, but a plugin or service must calculate differences, manage baselines, and support review. In this guide, the runnable setup uses the official Percy Cypress SDK as one documented option. The strategy applies equally to maintained local-diff integrations and other visual services.
A successful program depends less on taking many screenshots and more on controlling what appears in them. Stable data, clocks, fonts, viewports, animations, and review ownership turn visual noise into useful defect evidence.
TL;DR
| Decision | Practical recommendation |
|---|---|
| First coverage | Shared components and high-risk workflow states |
| Snapshot size | Component or region first, full page when layout is the requirement |
| Comparison platform | Local plugin for control, managed service for rendering and review workflow |
| Test data | Stub or seed deterministic scenario data |
| Time | Freeze browser time for date-dependent content |
| Responsive checks | Select representative layout breakpoints, not every width |
| CI policy | Require review of meaningful diffs and retain functional test evidence |
1. What Cypress Visual Testing Actually Verifies
A functional assertion answers a specific question: is the Save button enabled, did the URL change, or does the card contain the expected name? A visual comparison asks whether the rendered pixels or rendered DOM snapshot differ from an approved reference. It can reveal a defect the author did not anticipate enough to assert directly.
The workflow has three core stages:
- Capture: Cypress visits a page or mounts a component, creates deterministic state, and calls the integration's snapshot command.
- Compare: the tool compares the new rendering with a known baseline according to its comparison model.
- Review: a person decides whether each difference is a defect or an intentional design update.
The baseline is not automatically correct forever. It is a reviewed representation of expected appearance for a named state and rendering environment. If a team approves changes without understanding them, visual testing becomes a screenshot update ritual instead of a quality control.
Visual checks are strong at geometry, colors, images, icon placement, text wrapping, and responsive composition. They do not prove keyboard navigation, accessible names, business logic, API correctness, or that an invisible control works. Keep explicit functional and accessibility tests. A visual snapshot complements those layers.
The best candidates have important visual contracts: checkout summary, dashboard cards, navigation at breakpoints, empty and error states, modal composition, complex tables, and shared design-system components. A server health endpoint or purely data-level rule is not a visual test candidate.
2. Understand the Capture and Comparison Architecture
Visual tools integrate with Cypress in different ways. A local pixel plugin usually asks the browser to produce an image, compares it with a repository baseline on the same machine, and writes a diff artifact. A managed service may capture DOM and resources during the test, render snapshots in controlled cloud browsers, and present diffs in a hosted review workflow.
| Architecture | Baseline location | Rendering | Review experience | Main responsibility |
|---|---|---|---|---|
| Local pixel comparison | Usually repository or artifact storage | Your local or CI browser | Diff files and CI artifacts | Pin identical capture environments |
| Self-hosted review platform | Team infrastructure | Local agents or hosted workers | Web review, depends on product | Operate storage and service |
| Managed visual service | Provider | Provider-controlled browsers | Pull request and dashboard review | Configure states, data, and approvals |
Raw pixel comparison is sensitive to every changed pixel. This can be appropriate for canvas output, brand assets, or a fully pinned renderer. More perceptual comparison models can ignore small rendering noise while flagging meaningful layout changes, but thresholds and algorithms should never replace input control.
A DOM-capture service can render several browser and width combinations from one Cypress checkpoint. A local screenshot plugin normally requires your CI matrix to launch each desired environment. Neither is universally superior. Choose according to security requirements, application reachability, browser coverage, budget, storage, and review needs.
Do a short proof of concept with actual fonts, authentication, responsive states, and pull request flow. A tool that produces an impressive demo but cannot reach a private test environment or assign diff ownership will not survive production use.
3. Choose Local Diffing or a Managed Service
Start with the operating model, not a long feature list. Ask who will maintain baselines, where screenshots may be stored, how many rendering combinations matter, and how reviewers will approve changes.
Local diffing is attractive when images cannot leave controlled infrastructure, the browser matrix is small, and the team can maintain a pinned container. Baselines can receive normal repository review. The costs are repository growth, artifact workflow, rendering variance, and building an approval convention. Every developer and CI agent must compare in an equivalent environment.
A managed service is attractive when several browsers and viewports matter or when product, design, and engineering need a shared review screen. The service handles storage, diff presentation, and often rendering consistency. The costs include data governance review, provider dependency, authentication, and subscription management.
Use this selection checklist:
- Can the tool capture both end-to-end pages and isolated components?
- Does it render the browsers and widths required by the product support policy?
- Can it access protected assets, private environments, and authenticated states safely?
- Does it support masking or ignoring only narrowly defined dynamic regions?
- Are baseline branches and pull request comparisons understandable?
- Can CI fail clearly when snapshots are unreviewed or rejected?
- What data leaves the environment, and how long is it retained?
- Can the team export or migrate baseline history?
The Applitools vs Percy comparison offers a focused view of two managed approaches. Validate current product capabilities directly before procurement, since service features can change.
4. Set Up Cypress Visual Testing With Percy
Install Cypress if the project does not already use it, then install Percy's command-line runner and Cypress SDK.
npm install --save-dev cypress @percy/cli @percy/cypress
Import the integration once from the Cypress end-to-end support file:
// cypress/support/e2e.ts
import '@percy/cypress'
For TypeScript projects that restrict global types, include both packages in the Cypress TypeScript configuration:
{
"compilerOptions": {
"types": ["cypress", "@percy/cypress"]
},
"include": ["cypress/**/*.ts", "cypress.config.ts"]
}
Add a first snapshot after proving the page is stable:
describe('account overview', () => {
it('matches the approved populated state', () => {
cy.intercept('GET', '/api/account', { fixture: 'account.json' }).as('account')
cy.visit('/account')
cy.wait('@account')
cy.get('[data-cy=account-overview]').should('be.visible')
cy.get('[data-cy=loading]').should('not.exist')
cy.percySnapshot('Account overview, populated', {
widths: [375, 768, 1280],
})
})
})
Set the project token in the shell or CI secret store, never in source control, then wrap the Cypress command with Percy:
export PERCY_TOKEN=your_project_token
npx percy exec -- cypress run
The documented Cypress SDK accepts cy.percySnapshot([name][, options]). A unique, semantic name helps reviewers understand state. Percy SDK 3 and later use the setup above. Lock installed versions in package-lock.json, and review upgrade notes before changing the integration.
5. Design a Small, High-Value Snapshot Portfolio
A snapshot is a review obligation. When any covered component changes, someone must interpret the difference. Taking a full-page snapshot after every functional test multiplies duplicated evidence and teaches reviewers to approve mechanically.
Build a portfolio around risk:
- Shared primitives with broad blast radius, such as buttons, inputs, cards, dialogs, and navigation.
- Revenue or trust workflows, such as checkout, pricing, authentication errors, and account controls.
- Layout-heavy screens with tables, charts, sidebars, sticky regions, or responsive rearrangement.
- States users actually encounter: loading, populated, empty, validation error, service error, disabled, and success.
- Themes and localization only where the product explicitly supports them.
Prefer the smallest surface that proves the requirement. A component snapshot of an order card produces a focused diff when its badge moves. A full checkout page is justified when the relationship between summary, form, and sticky action area is the requirement.
Name snapshots by feature and state, not test implementation. Checkout, validation errors, mobile remains meaningful after spec refactoring. snapshot 7 and a generated timestamp do not. Ensure names remain unique within the visual build.
Maintain a lightweight coverage map listing snapshot name, owner, state source, widths, and why it exists. Remove duplicate checkpoints when a component-level snapshot already covers the same visual contract. A smaller trusted suite is more valuable than hundreds of noisy captures.
6. Stabilize the Page Before Taking a Snapshot
A snapshot command captures the current state. It cannot know whether a skeleton will disappear in the next frame or a web font is still loading. Cypress assertions should establish readiness first.
it('captures a loaded product grid', () => {
cy.intercept('GET', '/api/products', { fixture: 'products.json' }).as('products')
cy.visit('/products')
cy.wait('@products').its('response.statusCode').should('eq', 200)
cy.get('[data-cy=product-card]').should('have.length', 6)
cy.get('[data-cy=skeleton]').should('not.exist')
cy.document().its('fonts.status').should('eq', 'loaded')
cy.percySnapshot('Product grid, six products')
})
The font assertion uses the document font set exposed by browsers that support the CSS Font Loading API. If the application's support browser lacks that API, use an application-specific font readiness strategy or preload the test font in the controlled environment.
Disable or neutralize motion that does not belong to the target state. Managed tools may provide snapshot-specific CSS, while local setups can load a test stylesheet. Do not globally hide an animated component if animation layout is what you need to test. Instead, pause it at a defined representative frame or cover it through a dedicated component test.
Wait on product signals rather than generic quiet time. An aliased request, row count, loaded image state, or explicit ready marker is meaningful. cy.wait(2000) is still a race, and adding it before a snapshot only slows the normal path.
If a snapshot is flaky, identify which pixels change and trace them to data, time, motion, fonts, rendering environment, or genuine application nondeterminism. Raising a global difference threshold is usually the least informative response.
7. Control Data, Time, Randomness, and Personalization
Changing content causes valid visual differences that obscure layout defects. Use scenario fixtures or deterministic server seeds so every run renders the same names, prices, counts, images, and ordering.
it('captures a stable billing history', () => {
cy.clock(Date.UTC(2026, 6, 13, 9, 0, 0))
cy.intercept('GET', '/api/invoices', { fixture: 'invoices.json' }).as('invoices')
cy.visit('/billing')
cy.wait('@invoices')
cy.get('[data-cy=invoice-row]').should('have.length', 4)
cy.get('[data-cy=current-date]').should('contain.text', 'July 13, 2026')
cy.percySnapshot('Billing history, populated')
})
Freeze browser time before visiting when page scripts read the clock during initialization. Control server-generated timestamps in the fixture or seed response as well. A browser clock cannot change values already rendered by a backend.
Replace random IDs in visible text with fixed scenario values. Seed sorting ties deterministically. Use local test images or stable asset URLs and verify they have loaded. Avoid production news feeds, advertisements, rotating recommendations, live balances, and user-specific experiments unless the variation is the subject of a dedicated test.
Masking is appropriate for a narrow region that cannot be controlled, such as a third-party map attribution timestamp. Masking an entire dashboard because its data changes defeats visual coverage. Prefer deterministic inputs, then use the smallest possible exclusion and document why it exists.
The Cypress fixture example guide covers reusable fixture patterns. Remember that a stubbed visual test verifies presentation against controlled data. Retain contract and integration tests for the real service boundary.
8. Plan Responsive and Cross-Browser Coverage
Responsive visual testing should follow the design system's layout changes and the product's supported device classes. Checking dozens of adjacent widths adds review cost without necessarily adding unique behavior.
A practical matrix may include:
| Target | Illustrative width | Purpose |
|---|---|---|
| Small mobile | 375 | Stacked layout and compact navigation |
| Tablet | 768 | Breakpoint transition and medium content width |
| Desktop | 1280 | Standard multi-column layout |
| Wide desktop | 1440 | Maximum containers and persistent side panels |
These widths are examples. Use the breakpoints and analytics-backed support policy for your product. Capture just below or above a breakpoint when boundary behavior has historically failed.
Percy accepts widths per snapshot:
cy.get('[data-cy=dashboard]').should('be.visible')
cy.percySnapshot('Dashboard, populated', {
widths: [375, 768, 1280, 1440],
})
Cross-browser coverage addresses differences in layout engines, font rasterization, form controls, and CSS support. A managed renderer can produce several browsers from one captured state, depending on account configuration. A local-diff workflow needs a controlled CI matrix and distinct baselines where browser rendering legitimately differs.
Do not assert a desktop snapshot after merely resizing a mobile page if the application listens incorrectly to resize or fetches device-specific content only at load. Set the intended viewport before visiting when behavior depends on initial dimensions. Test responsive interaction functionally too, such as opening the collapsed navigation and verifying keyboard focus.
9. Use Component Testing for Focused Visual Contracts
Cypress Component Testing renders a component in isolation with controlled props and dependencies. This is a strong visual testing surface because the screenshot is small, data is explicit, and a diff points to one owner.
A React example assumes the project has completed Cypress Component Testing setup and exposes cy.mount() through its support file:
import { OrderCard } from '../../src/components/OrderCard'
describe('<OrderCard />', () => {
it('renders a delayed shipment warning', () => {
cy.mount(
<OrderCard
order={{
id: 'ord_101',
customerName: 'Asha Rao',
total: 79.5,
status: 'delayed',
}}
/>,
)
cy.get('[data-cy=order-card]').should('be.visible')
cy.get('[data-cy=status-badge]').should('have.text', 'Delayed')
cy.percySnapshot('Order card, delayed')
})
})
Create one case for each visually distinct state, not every internal prop permutation. Error, selected, disabled, long-content, and empty states often matter. Boundary content such as a long customer name can expose overflow and wrapping defects that normal fixtures miss.
Component visual checks do not replace a small number of page-level layout tests. A card can look correct alone but overlap a sibling in a grid. Use component tests for owned contracts and end-to-end snapshots for composition and critical workflows.
See Cypress component testing examples for mounting and test-boundary details. Keep provider wrappers, themes, and fonts equivalent to production so isolation does not create an unrealistic rendering.
10. Run Visual Testing in CI
A visual build should run from locked dependencies, a known browser environment, deterministic application state, and a protected token. The job must make unreviewed or rejected changes visible to pull request authors.
A package script keeps the command discoverable:
{
"scripts": {
"test:visual": "percy exec -- cypress run --spec 'cypress/e2e/visual/**/*.cy.ts'"
},
"devDependencies": {
"@percy/cli": "^1.30.0",
"@percy/cypress": "^3.0.0",
"cypress": "^15.0.0",
"wait-on": "^8.0.0"
}
}
The versions are illustrative compatible major ranges, not a recommendation to replace the versions already locked by your repository. Install normally and commit the generated lockfile. Avoid hand-editing dependency ranges without resolving them.
A GitHub Actions job can start the application, wait for it, and run the script:
name: Visual tests
on:
pull_request:
jobs:
visual:
runs-on: ubuntu-latest
timeout-minutes: 20
env:
PERCY_TOKEN: ${{ secrets.PERCY_TOKEN }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- run: npm ci
- name: Start application
run: npm run dev -- --host 0.0.0.0 &
- run: npx wait-on http://127.0.0.1:3000
- run: npm run test:visual
- uses: actions/upload-artifact@v4
if: failure()
with:
name: cypress-failure-artifacts
path: |
cypress/screenshots
cypress/videos
if-no-files-found: ignore
Match the port to the application. Pin action major versions according to organizational policy, restrict secret exposure on untrusted forks, and never print the Percy token.
11. Govern Baselines and Pull Request Review
Baseline approval changes the expected product appearance. It deserves the same care as source changes. The pull request should explain why the UI changed, link the design or requirement when available, and name the states affected.
Use these review rules:
- The author checks every diff and classifies it as intended, unintended, or environmental noise.
- The owning engineer or designer approves meaningful visual changes according to team policy.
- Baselines update only from the intended source branch and rendering environment.
- Unexplained widespread changes block approval until fonts, assets, and environment are investigated.
- Removed components also remove obsolete snapshots and ownership records.
A large diff can be correct, but bulk acceptance should never be the default. Filter by snapshot and width, inspect unexpected neighboring regions, and compare the code change with the visual blast radius. If a one-line token update changes hundreds of snapshots, sample every component family and confirm the design-system intent.
For repository-stored baselines, protect generated files from accidental local-environment updates. Document the container or CI job that creates approved images. For managed services, configure branch baselines and access roles so a feature branch cannot silently redefine main.
Track review health qualitatively: recurring noise causes, snapshots with no owner, and diffs repeatedly approved without inspection. The goal is trusted signal, not a maximum snapshot count.
12. Debug Visual Diffs Systematically
Start by asking whether the difference represents product code, test input, or rendering environment. The highlighted region usually points toward one class.
| Diff pattern | Likely cause | Investigation |
|---|---|---|
| Every text edge changes | Font or browser rendering | Confirm font load, browser, OS, and image |
| Dates or countdowns change | Uncontrolled clock | Freeze browser and server time |
| Rows have different content | Live or shared data | Stub or seed deterministic records |
| One component shifts | CSS or parent layout change | Inspect computed styles and containing block |
| Animated area differs | Capture timing | Pause animation at a defined state |
| Images are blank | Asset loading or access | Verify request, credentials, and load completion |
| All snapshots change | Environment or global token | Check dependency, browser, font, and theme changes |
Reproduce with the same commit, data, browser, viewport, and capture command. A developer laptop and Linux CI can rasterize local pixel screenshots differently. If the baseline is produced in CI, investigate there or use the identical container locally.
Do not immediately increase the allowed difference percentage. A threshold can be useful for known rendering characteristics, but it also reduces sensitivity everywhere it applies. First remove time, data, animation, and environment variance. If a narrow exclusion remains necessary, document it beside the snapshot.
Retain Cypress functional failures as well as the visual service link. A snapshot may never be sent if the test fails while creating state, and reviewers need the command log, screenshot, or request evidence to distinguish setup failure from visual change.
13. Cypress Visual Testing Best Practices
- Capture named business states after explicit readiness assertions.
- Keep data, time, locale, timezone, fonts, images, and feature flags deterministic.
- Prefer components and regions, then add full pages only for composition risk.
- Select widths around real layout breakpoints and supported device classes.
- Separate snapshot setup from assertions that prove functional readiness.
- Keep authentication tokens in CI secrets and review what DOM or image data leaves the environment.
- Lock dependencies and use a consistent browser or managed rendering environment.
- Assign every snapshot to a feature owner and remove obsolete coverage.
- Require explanation and review for baseline changes.
- Pair visual coverage with keyboard, accessibility, API, and business-rule tests.
A useful snapshot failure answers: which named state changed, at which width or browser, and how can the owner reproduce it? If the suite cannot answer those questions, improve naming and evidence before adding more checkpoints.
Interview Questions and Answers
Q: Does Cypress have built-in visual comparison?
No. cy.screenshot() captures an image but does not compare it with a baseline. A maintained plugin or service supplies comparison, storage, and review. Cypress remains responsible for driving and stabilizing application state.
Q: How would you choose between local and cloud visual testing?
I compare data governance, browser coverage, environment access, review workflow, storage, and operating cost. Local diffing offers control but requires a pinned renderer and baseline workflow. A managed service simplifies cross-browser rendering and review but adds provider and data considerations.
Q: Why prefer component snapshots?
They isolate the rendering contract, use controlled inputs, and produce focused diffs with a clear owner. They are cheaper to review than large pages. I still keep selected page snapshots for composition and responsive layout.
Q: How do you reduce false visual failures?
I freeze time, control data, pin viewport and environment, load fonts and images, disable irrelevant motion, and assert readiness before capture. I use narrow masking only when a dynamic region cannot be controlled. I do not start by loosening thresholds.
Q: What should happen when a visual diff is intentional?
The pull request should explain the design change and the owner should inspect every affected state. Approval updates the expected baseline through the authorized workflow. A bulk accept with no review is not sufficient evidence.
Q: Can visual tests replace functional assertions?
No. A correct screenshot cannot prove that a button works, an API used the correct payload, or keyboard focus is valid. Functional and accessibility checks provide semantic evidence, while visual tests cover appearance.
Q: What makes a good snapshot name?
It identifies the feature and meaningful state, such as Checkout, declined payment, mobile. It stays useful after spec refactoring and is unique in the build. Generated sequence numbers and timestamps are poor names.
Q: How would you debug all text changing in CI?
I would check whether the intended web font loaded, then compare browser, OS, image, locale, and dependency versions. Widespread text-edge changes often indicate environment drift rather than a product CSS edit. I would reproduce in the baseline environment before approval.
Common Mistakes
- Treating
cy.screenshot()as if it performs a baseline comparison. - Capturing before data, fonts, images, or animations have reached the intended state.
- Using production or shared live data that changes names, counts, and ordering.
- Adding a full-page snapshot to every functional test.
- Masking large regions instead of controlling inputs.
- Raising global difference thresholds to silence environment noise.
- Comparing laptop baselines with screenshots from a different CI browser and operating system.
- Approving every changed baseline because the build is blocked.
- Testing only one desktop width for a responsive product.
- Assuming a visual pass proves accessibility or interaction behavior.
- Exposing service tokens or sensitive customer data in snapshots and logs.
Conclusion
Cypress visual testing is a controlled-state and review discipline. Cypress gets the application to a known point, the visual integration captures and compares it, and an accountable reviewer decides whether the difference is acceptable. The snapshot command is the smallest part of that system.
Begin with five to ten high-risk component and workflow states. Stabilize their inputs, run them through a pinned CI path, and require deliberate review. Expand only while the suite remains quiet enough that every failure receives real attention.
Interview Questions and Answers
Describe a Cypress visual testing architecture.
Cypress creates a deterministic page or component state and invokes a snapshot integration. The visual tool captures an image or DOM representation, compares it with the branch baseline, and exposes a review result. CI reports functional setup failures and visual approval status separately.
Why does Cypress need a plugin or service for visual comparison?
Cypress includes screenshot capture but no baseline comparison engine or approval workflow. Integrations supply pixel or perceptual comparison, storage, browser rendering, and review. This separation lets teams choose an operating model.
What would you stabilize before a snapshot?
I control data, clock, timezone, locale, viewport, browser, fonts, images, animations, feature flags, and authentication state. I wait on explicit application readiness. Any uncontrolled visible input can create noise.
How do you decide snapshot granularity?
I choose the smallest surface that proves the visual requirement. Components cover owned states, while selected pages cover composition and breakpoint behavior. Every snapshot must justify its ongoing review cost.
How would you govern baseline changes?
Baseline updates occur through a protected branch-aware workflow. The author explains the product change, and the relevant owner inspects all affected states and widths. Unexplained global changes are investigated, not bulk approved.
What are the tradeoffs of local pixel comparison?
It keeps images and control in team infrastructure and can be inexpensive. It also makes the team responsible for identical rendering environments, baseline storage, diff artifacts, and review. Raw pixels are sensitive to font and browser variance.
How do you select responsive visual coverage?
I use supported device classes and the design system's actual breakpoints. I include boundary widths when layout transitions are risky, and avoid redundant adjacent sizes. Responsive interactions also receive functional tests.
Why can a visual test pass while the product is broken?
A baseline can faithfully show a button that looks right but does nothing, or markup with incorrect accessibility semantics. Visual comparison only proves similarity to approved appearance. Functional, API, and accessibility evidence are still required.
Frequently Asked Questions
Can Cypress do visual testing?
Yes, Cypress can drive the application and call a visual testing integration. Cypress does not itself compare screenshots, so teams use a plugin or managed service for baselines, diffs, and review.
What is the difference between cy.screenshot and visual testing?
`cy.screenshot()` creates an image artifact. Visual testing adds comparison against an approved baseline, difference reporting, and a process for accepting intentional changes.
How do I install Percy with Cypress?
Install `@percy/cli` and `@percy/cypress`, import `@percy/cypress` in the support file, and call `cy.percySnapshot()`. Run Cypress through `npx percy exec -- cypress run` with `PERCY_TOKEN` provided securely.
How can I prevent flaky Cypress visual tests?
Control fixtures, time, locale, viewport, fonts, images, animation, and feature flags. Assert the exact ready state before capture and use the same rendering environment for baseline and comparison.
Should visual tests capture full pages or elements?
Prefer components or regions when they prove the contract because their diffs are focused. Use full-page snapshots for composition, responsive layout, and workflows where relationships across regions matter.
Should visual baselines be committed to Git?
Local pixel tools often store baselines in the repository, while managed services store them remotely. Either model needs protected updates, a consistent renderer, clear ownership, and pull request review.
Do Cypress visual tests replace accessibility tests?
No. Image comparisons cannot reliably prove semantics, focus order, keyboard operation, or accessible names. Run visual, functional, and accessibility checks as complementary layers.