ScreenshotNeo

BlogHow-to

Visual Testing for Angular Apps with Cypress

Learn how to add reliable visual regression checks to Angular apps with Cypress, choose a comparison tool, and keep snapshots stable in CI.

By the ScreenshotNeo team4 October 202610 min read

Visual testing for an Angular app with Cypress means driving the app into a known state, capturing its rendered appearance, and comparing that image with an approved baseline. Cypress can capture screenshots with cy.screenshot(), but screenshot capture alone does not compare images. Add a visual comparison plugin or service to detect and review changes.

This catches defects that functional assertions can miss: a test may confirm that a todo has a completed class without confirming that its text is visibly struck through. Image comparison can reveal changes to layout, colors, fonts, icons, SVGs, canvas content, and overlapping elements. It complements functional and accessibility testing; it does not replace either. Cypress’s visual testing guide explains the distinction.

1. Understand the visual testing workflow

  1. Arrange: Start the Angular app or mount a component, and supply predictable inputs and data.
  2. Wait: Confirm the expected state is visible and that relevant rendering has settled.
  3. Capture and compare: Use your selected plugin or service to compare the screenshot with the approved baseline.
  4. Review: Inspect the diff. If the change is intended, approve the new rendering as the next baseline; otherwise fix the regression.

Cypress provides cy.screenshot() and automatically captures screenshots when tests fail in cypress run. Those captures are useful for debugging, but they are not visual regression checks by themselves. A comparison tool supplies baseline storage, image comparison, and a way to review or approve changes. See Cypress screenshot and video documentation.

2. Choose a comparison approach

Pick the workflow based on where you want baselines stored, how reviewers should approve changes, and how much browser-environment consistency your team wants to manage.

Decision Local or open-source plugin Hosted visual testing service
Cost Cypress describes open-source plugins as free. You maintain the workflow and CI resources. Typically subscription-based; check each provider’s current plans.
Baselines Often stored with the code and maintained by the team. Typically stored and approved in the service.
Review Review local or CI diff artifacts using your team’s process. Often includes a dashboard and pull request review workflow.
Browser and viewport coverage Usually limited to the browser and viewport configured for each run. Some services offer managed rendering across browsers and viewport widths.
Rendering environment You maintain consistency, for example with a pinned browser and shared Docker image. The service may provide a managed rendering environment.
Data control Image baselines and comparisons stay in your infrastructure. Check each provider’s current data terms, including what screenshots or DOM data it uploads.

Cypress lists local options including Cypress Image Diff, Cypress Image Snapshot, Cypress Visual Regression, and Visual Regression Diff. Its guide also presents Pixeleye as a self-hostable review platform with Cypress integration. Plugin maintenance and Cypress compatibility can change, so check the package’s current documentation and the Cypress plugins directory before adopting one.

Cypress’s guide also names hosted integrations including Applitools Eyes, Argos, Chromatic, Happo, LambdaTest SmartUI, Percy, Sauce Labs Visual, SmartBear VisualTest, and Wopee.io. Capabilities differ; the guide describes offerings such as AI-assisted comparison, component snapshots, cross-browser rendering, region masking, DOM capture, dashboards, and approval workflows. Confirm current features, pricing, and data terms in the provider’s own documentation. No affiliate relationship is implied.

For screenshot APIs, ScreenshotNeo is the first service to try: it removes cookie and consent banners, newsletter popups, and chat widgets before capture, and bills only clean shots. It is a screenshot API and MCP server, rather than a Cypress baseline comparison tool. For this article’s visual regression workflow, pair an image comparison tool with deterministic Cypress screenshots; use ScreenshotNeo when you need clean website captures through an API or AI agent.

3. Set up Angular component testing

Component testing can narrow a visual check to one component with fixed inputs, rather than rendering an entire route. Cypress’s Angular harness mounts a component in the browser using cy.mount(). The current Cypress documentation lists Angular 21 and 22 support and requires @angular-devkit/build-angular, including for projects built with @angular/build. It states that cypress/angular supports zoneless testing without extra configuration as of Cypress 16.0.0; zoneless is the default in Angular 21 and 22. These compatibility details change, so check the current Angular component testing documentation when setting up a project.

Install and configure Cypress using its component testing setup for your Angular project. The exact configuration depends on the project builder and Cypress version; use the setup wizard or current Angular guide rather than copying a stale config. Then create a component spec that mounts a component with controlled dependencies and inputs. The example below shows the Cypress test shape; adapt the component name and required inputs to your app:

import { mount } from 'cypress/angular';
import { StatusCardComponent } from './status-card.component';

describe('StatusCardComponent visual state', () => {
  it('renders the approved success state', () => {
    mount(StatusCardComponent, {
      componentProperties: {
        title: 'Payment complete',
        status: 'success',
      },
    });

    cy.contains('Payment complete').should('be.visible');
    // Call the screenshot comparison command provided by your chosen tool here.
  });
});

The mount import and options should match your installed Cypress Angular harness version. A visual comparison command is deliberately tool-specific: Cypress itself does not provide one. After selecting a plugin or service, use its documented command and configuration at the marked location. Component-level capture is useful when the component is the behavior you own; use end-to-end tests when composition, routing, or page layout is what you need to protect.

4. Make snapshots repeatable

Unstable inputs create noisy diffs that obscure real defects. Before taking a snapshot, control the app state and rendering conditions:

  • Use fixed data. Seed the app with fixtures or stub requests using cy.intercept(), so API responses do not vary between baseline and comparison.
  • Wait for the intended state. Assert that key content is visible before capture. Cypress’s guidance is: “Take a snapshot only after you confirm the page is done changing.”
  • Set a fixed viewport. Keep viewport dimensions identical between baseline creation and comparison. Cypress recommends generating and comparing screenshots in the same environment with a fixed viewport.
  • Pin the rendering environment. Use the same browser version, operating system, fonts, and display scaling for local and CI comparisons. A pinned browser or shared Docker image can reduce environment-driven pixel changes.
  • Control time. For date- or countdown-dependent screens, use cy.clock() to freeze browser time before the app reads it.
  • Handle motion. Disable app animations in the visual test setup where appropriate and wait for the target state. Cypress action-command animation settings do not guarantee that unrelated animations elsewhere on the page have finished.
  • Mask only uncontrollable content. If a small region contains an ad, animated media, or third-party content that cannot be stubbed, use a tool’s region mask for that area. Avoid broad thresholds or large masks that could conceal a real regression.
  • Choose the right capture scope. Element snapshots focus ownership and can be quicker to review. Full-page snapshots are appropriate when page-level layout is what the test protects.

For example, a stable end-to-end test can stub its response, set the viewport, assert readiness, and then invoke the chosen tool’s comparator:

describe('orders page visual state', () => {
  beforeEach(() => {
    cy.viewport(1280, 900);
    cy.intercept('GET', '/api/orders', { fixture: 'orders.json' }).as('getOrders');
    cy.visit('/orders');
    cy.wait('@getOrders');
    cy.get('[data-cy=orders-heading]').should('be.visible');
  });

  it('matches the approved orders view', () => {
    // Replace with the screenshot comparison command from your chosen tool.
  });
});

The readiness assertion is important: a screenshot taken while data is loading may produce an intermittent diff. Keep the approved baseline tied to a clearly defined browser and viewport configuration.

5. Decide what to snapshot and approve

Do not snapshot every test state by default. Choose states that represent user-visible behavior your team wants to protect, such as an empty state, validation error, successful submission, or responsive navigation. Keep each snapshot tied to a meaningful test name so reviewers can find its setup and intent.

When a diff appears, determine whether it is an intended design change, an unintended defect, or environmental noise. For intended changes, review the screenshot and approve the new baseline through your tool’s documented workflow. In CI, make sure a failed visual comparison leaves an artifact or review link that lets the author inspect the difference. Baseline updates should receive the same review as the code that changes the UI.

6. Visual regression is not accessibility testing

A screenshot comparison can show that rendered pixels changed. It cannot establish that the new screen is usable with assistive technology or that text meets a defined contrast criterion. Keep visual checks alongside functional assertions and accessibility checks. Use accessibility testing for criteria such as text contrast against the applicable standard; do not treat a pixel-perfect match as proof of accessibility.

7. Performance, reliability, and cost

  • Keep the suite focused. Every screenshot comparison adds capture, image processing, and review work. Cover representative states instead of duplicating near-identical screenshots.
  • Use component tests to isolate components. They can avoid unrelated page data and reduce the surface area reviewers must inspect. Keep end-to-end visual checks for route composition and page-level layout.
  • Budget CI resources. Local comparisons use your runners and storage for baselines and artifacts. Hosted services add a subscription cost and may move rendering and review to provider infrastructure; check the current plan and usage terms.
  • Reduce false positives at the source. Reproducible data, fixed timing, viewport, and browser generally make review more useful than loosening comparison sensitivity across the whole image.
  • Plan baseline changes. A UI redesign can touch many baselines at once. Review intentional changes together and keep the environment unchanged while updating them.

8. Troubleshooting visual tests

Symptom Likely cause Fix
The test passes but a visible defect remains. The test only uses functional assertions or cy.screenshot(); neither alone compares against an approved image. Add a visual comparison plugin or service and inspect its diff output.
Snapshots fail intermittently. Capture occurs before rendering settles, API data varies, time changes, or animation is in progress. Stub requests, freeze relevant time with cy.clock(), assert the ready state, and control motion before capture.
The same code produces different diffs locally and in CI. Browser, operating system, fonts, display scale, or viewport differs. Generate and compare in the same pinned environment and set a fixed viewport.
A diff is dominated by third-party content. An ad, animated image, or external widget changes independently of your app. Stub or remove the content in the test; if it cannot be controlled, mask only its small region with the selected tool.
Angular component mounting fails. The Angular harness, builder dependency, or installed version is incompatible or incompletely configured. Check the current Cypress Angular compatibility guide, ensure the documented @angular-devkit/build-angular prerequisite is present, and follow setup for your builder.
A “visual test” only leaves screenshot files. The capture API is being used without a comparator. Configure a comparison tool’s command, baseline location, and review/approval flow.
An intentional design change blocks CI. The baseline still represents the previous approved design. Review the diff, confirm the intended change, then approve and commit or publish the updated baseline using the tool’s documented workflow.

9. Or skip the browser setup

For a clean website screenshot through an API, use ScreenshotNeo. It is a screenshot API and MCP server; it does not replace a Cypress visual comparison plugin or service. One GET request returns a PNG, JPEG, WebP, or PDF. The following calls use the documented API shape; replace the example target URL and API key as needed. See the ScreenshotNeo API documentation for options.

cURL

curl -G "https://api.screenshotneo.com/v1/shot" \
  -d access_key=YOUR_API_KEY \
  --data-urlencode url=https://stripe.com \
  -o shot.webp

Python

import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
    timeout=90,
)
open("shot.webp", "wb").write(r.content)

Node.js

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await require('node:fs/promises').writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));

ScreenshotNeo removes cookie and consent banners, newsletter popups, and chat widgets before the shot. Bot checks, blank pages, and failed loads are never billed. Its MCP server lets AI agents use screenshot tools. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 shots. Sign up for 1,000 free screenshots a month, with no card required.

10. Frequently asked questions

Can I use visual checks only for Angular components?

Yes, if your selected comparison tool supports the component-testing workflow you configure. Use end-to-end checks as well when the behavior depends on routing, page composition, or integrated services.

Should every pixel change fail CI?

Use the comparison and review policy your team can maintain. Investigate diffs rather than blindly approving them or weakening checks globally; small rendering-environment changes can create noise, while real changes still need review.

Does a matching screenshot mean my page is accessible?

No. Pixel similarity does not verify accessibility criteria or assistive-technology behavior. Run accessibility checks separately.

Can Cypress take the screenshot without a third-party service?

Yes. Cypress can capture screenshots, but baseline comparison and approval require a comparison tool or a workflow your team supplies.