Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Implementing Visual Snapshot Testing with Playwright

Tech May 15 1

Visual snapshot testing in Playwright operates on a baseline copmarison principle. The typical workflow involves:

  1. Running the test suite initially to capture reference images (baselines).
  2. The first execution will fail because no baseline exists; the runner saves the current screenshots as references.
  3. Subsequent runs compare new captures against these saved baselines. If pixel differences exceed the threshold, the test fails.

Environment Setup

Ensure Node.js is installed. Using TypeScript is recommended for better IDE support and type safety. Configure the Taobao registry to handle network restrictions:

npm install -D @playwright/test --registry=https://registry.npmmirror.com
npm install -D typescript --registry=https://registry.npmmirror.com
npx playwright install
mkdir -p specs
touch specs/visual-check.spec.ts

Basic Snapshot Test

Create a test that navigates to a target URL and asserts the visual state.

import { test, expect } from '@playwright/test';

test('Verify landing page layout', async ({ page }) => {
  await page.goto('https://example.com');
  await expect(page).toHaveScreenshot();
});

Execute the suite using:

npx playwright test

The first run generates the baseline image. Re-running the command confirms the test passes if the UI remains unchanged.

Test Execution Options

Viewing HTML Reports Generate an interactive report to inspect results and thumbnails:

npx playwright test --reporter html

Debug Mode Run tests with the UI interface to observe browser behavior:

npx playwright test --ui

Updating Baselines

If the UI changes intentionally, update the reference images:

npx playwright test --update-snapshots

Capturing Full Page Content

By default, Playwright captures the viewport. To capture the entire scrollable page:

test('Full page visual check', async ({ page }) => {
  await page.goto('https://example.com');
  await expect(page).toHaveScreenshot({ fullPage: true });
});

Targeting Specific Elements

Isolate specific components rather than the whole page for more resilient tests.

test('Verify submit button appearance', async ({ page }) => {
  await page.goto('https://example.com');
  const submitBtn = page.getByRole('button', { name: 'Submit' });
  await expect(submitBtn).toHaveScreenshot();
});

Clipping a Specific Region

Define a specific rectangular area to capture.

test('Check header region', async ({ page }) => {
  await page.goto('https://example.com');
  await expect(page).toHaveScreenshot({
    clip: { x: 0, y: 0, width: 800, height: 200 }
  });
});

Masking Dynamic Content

Hide sensitive or dynamic data (like usernames or ads) by masking them during capture.

test('Mask dynamic widgets', async ({ page }) => {
  await page.goto('https://example.com');
  await expect(page).toHaveScreenshot({
    mask: [page.locator('.user-avatar'), page.locator('.advertisement')]
  });
});

Best Practices

  • Focus on static UI elements to reduce false positives.
  • Use fixed test data sets to ensure consistency across environments.
  • Utilize masking to ignore areas that change frequently (timestamps, user info).

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.