How to Set Up Playwright Screenshot Tests for an Indian Ecommerce Website
Set up Playwright visual tests for an Indian ecommerce site, with stable regional fixtures, reviewed screenshot baselines, CI guidance, and runnable code.
Use Playwright Test’s expect(page).toHaveScreenshot() to create visual baselines for an Indian ecommerce site’s important journeys. Start with deterministic test data for the delivery region, currency display, products, and checkout state; pin the Playwright version and browser environment; then review and commit the initial screenshots. The examples below use TypeScript and Chromium desktop plus mobile WebKit. Adapt routes, fixture values, and browser projects to your application and customers.
Screenshot checks verify how a configured state renders. They do not decide whether a tax, payment, delivery, or other commercial rule is legally or commercially correct. Have the responsible product and compliance owners define expected values.
1. Install Playwright Test
For a new project, use the official initializer. For an existing Node.js project, add the test package directly. Keep the package version in the lockfile and install matching browser binaries; Playwright browser binaries are tied to Playwright versions and may need reinstalling after an upgrade.
# New project
npm init playwright@latest
npx playwright install
# Existing Node.js project
npm install --save-dev @playwright/test
npx playwright install
See the official Playwright installation guide and browser documentation for current setup details and browser installation options.
2. Configure a focused browser and viewport matrix
Begin with a small set of environments that reflects your customers and release risks. Each browser and viewport combination can require its own screenshot baseline, so adding projects increases review and maintenance work. The project names below are examples; check Playwright’s current device registry when selecting device descriptors.
// playwright.config.ts
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
testDir: './tests',
fullyParallel: true,
reporter: 'list',
use: {
baseURL: process.env.E2E_BASE_URL ?? 'http://127.0.0.1:3000',
trace: 'retain-on-failure',
},
projects: [
{
name: 'chromium-desktop',
use: { ...devices['Desktop Chrome'] },
},
{
name: 'webkit-mobile',
use: { ...devices['iPhone 13'] },
},
],
expect: {
toHaveScreenshot: {
animations: 'disabled',
caret: 'hide',
},
},
});
Choose projects using audience data, supported browsers, and known rendering risks. Playwright supports Chromium, Firefox, WebKit, branded browser channels, and emulated mobile and tablet devices. Keep the operating system, Playwright package, browser binaries, viewport, and headless settings consistent between baseline creation and comparison. Rendering can vary across these environments.
3. Choose deterministic ecommerce journeys
Cover states customers depend on, not every possible combination. A useful starting set is:
- A home or campaign page backed by a seeded campaign.
- A product listing with stable products, filter, and sort order.
- A product detail page with its primary image loaded and a known variant selected.
- A cart with fixed item, quantity, price display, and availability.
- A delivery or address step with a deterministic test location.
- A checkout review page with the application’s configured labels and totals.
For an India-facing store, make the relevant regional state explicit in your fixtures: for example, a seeded PIN code or delivery region, the configured rupee or other currency representation and precision, and the store’s own tax, delivery-fee, offer, payment, and checkout text. Add location-dependent availability or offers only where your application supports them. These are test dimensions, not assumptions about what every Indian store must display.
Seed or mock inventory, product images, account state, promotions, and delivery eligibility. Avoid capturing a live catalogue whose content can change independently of your code. Playwright recommends independent tests with isolated cookies, storage, and data state; see its best practices.
4. Write a page-level visual test
Use a route that returns controlled test data. Assert the expected user-visible state before taking the screenshot. The screenshot assertion waits for two consecutive screenshots to match before comparing against the baseline.
// tests/product-list.spec.ts
import { test, expect } from '@playwright/test';
test('Mumbai footwear listing renders correctly', async ({ page }) => {
await page.goto('/test-fixtures/category/footwear?region=mumbai');
await expect(page.getByRole('heading', { name: 'Footwear' })).toBeVisible();
await expect(page.getByRole('list', { name: 'Products' })).toBeVisible();
await expect(page).toHaveScreenshot('footwear-listing.png', {
fullPage: true,
});
});
The path, heading, and accessible name are illustrative; replace them with your own stable fixture route and semantics. Prefer roles, labels, and visible text over selectors tied to internal CSS classes. Use a page screenshot when layout and the full journey matter. For a focused component, capture just that component:
await expect(page.getByTestId('product-card-101'))
.toHaveScreenshot('product-card.png');
Use a test ID when it is a deliberate stable test contract. Otherwise prefer a user-visible locator. A component screenshot can reduce unrelated page volatility, while a page screenshot can catch layout changes across sections.
5. Control screenshot noise without hiding regressions
Playwright’s toHaveScreenshot() supports animation control, caret hiding, masks, and a stylesheet path for normalizing volatile regions. See the PageAssertions API for available options and current syntax.
await expect(page).toHaveScreenshot('checkout-review.png', {
fullPage: true,
animations: 'disabled',
caret: 'hide',
mask: [page.getByTestId('rotating-third-party-ad')],
maskColor: '#777',
});
Use masks only for content that is both genuinely nondeterministic and irrelevant to the behavior under test, such as a rotating third-party ad. Do not mask prices, delivery eligibility, product images, stock notices, or checkout totals when those are the things the test should protect. Prefer stable fixtures over masking. If a timestamp or other irrelevant value must be normalized, use a narrowly scoped stylesheet with the API’s stylePath option and keep that rule limited to the volatile element.
Wait for application data and important images to reach a known state before comparison. The screenshot assertion’s stability wait is useful, but it does not make changing server data deterministic. Disable animations for visual checks when motion is not part of the scenario; create separate interaction tests when animation behavior itself matters.
6. Generate, review, and update baselines
Run the tests to create the first expected screenshots, inspect them, and commit approved snapshots with the test code. A generated baseline is a reference image, not evidence that the current UI is correct.
npx playwright test
# After reviewing an intentional visual change:
npx playwright test --update-snapshots
When a comparison fails, inspect the expected, actual, and diff images. Determine whether the change is an intended design update, an environment mismatch, unstable data, or a product regression before updating the baseline. Do not regenerate snapshots merely to make a failing check pass. See the official visual comparisons guide.
7. Run the suite consistently in CI
Use the same pinned Playwright package and browser installation used to create the approved baselines. A consistent CI image is usually the simplest way to avoid local-versus-CI operating system differences. Run visual checks on pull requests when suite duration fits the team’s workflow, and retain actual, expected, and diff artifacts according to your repository’s CI practices.
Add Firefox, more desktop browsers, or more mobile projects when customer usage, support commitments, or observed defects justify the extra baselines. Cloud browser execution is an optional scaling choice for teams that need broader device coverage; BrowserStack documents Playwright cloud testing. Check current support, pricing, security requirements, and terms directly before adopting a service.
8. Troubleshoot common failures
| Symptom | Likely cause | What to do |
|---|---|---|
| Many pixels differ on a developer machine but not in CI | Different operating system, browser binary, Playwright version, headless setting, or hardware rendering. | Run baseline creation and comparison in the same pinned environment. Reinstall browser binaries after changing the Playwright version. |
| The first run reports a missing screenshot | No approved baseline exists yet. | Review the generated image for correctness, then commit it as the reference. Do not accept it without review. |
| The same test fails intermittently | Unseeded data, changing promotions or inventory, late images, animations, or third-party content. | Use a controlled fixture, wait for the meaningful page state, disable irrelevant animation, and narrowly mask only irrelevant external volatility. |
| The baseline changes for every browser or device | Different projects render at different sizes or engines and need distinct baselines. | Keep projects explicit and compare each project only with its own generated snapshots. Reduce the matrix to environments the team needs. |
| A locator times out before the screenshot | The route, accessible name, test data, or expected state is wrong or not ready. | Check the fixture route and rendered semantics; wait for the correct visible state rather than adding an arbitrary sleep. |
| Images appear blank or incomplete | The test captured before images loaded, the fixture’s asset path is unavailable, or remote image delivery is variable. | Serve stable test assets and wait for the primary image to load before the screenshot. |
| Snapshot update creates unexpectedly large diffs | A real layout or data change, or an environment mismatch affecting the whole page. | Compare image artifacts and verify environment and fixture inputs before accepting updates. |
9. Balance coverage, performance, reliability, and cost
- Coverage: Add browsers and viewport sizes based on customer usage and release risk. Every added combination creates more screenshots to review.
- Runtime: Start with a short set of high-value journeys, use isolated deterministic fixtures, and capture a component when a full-page image adds no useful coverage. Parallel execution may help, but ensure tests do not share mutable data.
- Reliability: Keep baselines and comparisons in the same environment, pin versions, and avoid live production data. Review visual diffs instead of treating every changed pixel as a product defect.
- Cost: Local Playwright uses your own compute and browser binaries. CI and optional cloud browser execution consume team or provider resources; compare current plan limits and terms before expanding. There is no meaningful fixed cost estimate without your CI setup and browser matrix.
- Regional correctness: A screenshot verifies rendered fixture values. It cannot validate whether a tax, payment, or delivery rule is correct; keep rule ownership and assertions with the appropriate product and compliance teams.
Or skip the browser setup
If you need screenshot files from URLs without maintaining a Playwright browser environment, ScreenshotNeo is a website screenshot API and MCP server. One GET request returns an image or PDF; its API documentation covers the options and parameters.
curl -G "https://api.screenshotneo.com/v1/shot" \
-d access_key=YOUR_API_KEY \
--data-urlencode url=https://your-store.example/products/footwear \
-o shot.webp
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={
"access_key": "YOUR_API_KEY",
"url": "https://your-store.example/products/footwear",
},
timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({
access_key: 'YOUR_API_KEY',
url: 'https://your-store.example/products/footwear',
});
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await Bun.write('shot.webp', res);
Cookie banners are accepted and more than 60 known consent platforms, newsletter popups, and chat widgets are removed before the shot; each step can be turned off. Bot checks, blank pages, timeouts, and failed loads are not billed, and cache hits cost nothing; response headers report the page verdict and billing status. An MCP server lets AI agents use screenshot, page-info, and PDF-capture tools. The free plan includes 1,000 screenshots per month with no card, and paid plans start at $5 for 3,000 shots. These URL captures complement browser-based assertions when you need screenshot files from pages; they do not replace your app’s deterministic fixture and baseline review process.
Sign up free for 1,000 screenshots a month, with no card required.
FAQ
Should I take a screenshot of the entire checkout?
Use a full-page capture when cross-section layout is part of the risk. For a focused price card or address panel, a component screenshot can make failures easier to understand.
Do I need a separate baseline for mobile?
Yes. A mobile project has a different viewport and often a different browser engine, so its screenshots should be generated and reviewed in that project.
Can these screenshots validate the correct tax or payment rule?
No. They show how the state supplied by your test renders. Define and verify business rules separately, then use visual tests to protect their presentation.
When should I add another browser?
Add one when audience data, support requirements, or a browser-specific defect makes the additional baseline and maintenance worthwhile.


