How to Test an Indian Ecommerce Site’s Product Pages with Screenshot Comparisons
Use Playwright screenshot comparisons to catch product-page regressions, cover key shopping states, and review India-specific listing details.
Use Playwright Test’s built-in toHaveScreenshot() assertion to compare a product page against an approved reference image. Start with a stable browser and viewport, cover representative product states, and review every diff before updating a baseline. Pair visual checks with functional assertions: pixels can show that a price or button changed, but they cannot tell you whether the displayed value is correct.
This guide builds a runnable TypeScript example for a product page, explains baseline management and CI, and includes checks for India-specific listing content where applicable. For a DIY workflow, the screenshots and baselines stay with your Playwright tests. For a single-call capture without browser setup, see ScreenshotNeo.
1. Set up Playwright screenshot comparisons
Install Playwright Test and its browser. The commands below use npm; use the same lockfile and dependency installation process in local development and CI.
npm init -y
npm install --save-dev @playwright/test
npx playwright install chromium
Create playwright.config.ts. Fix the browser project, viewport, device scale factor, locale, and timezone so screenshots are generated under consistent settings.
import { defineConfig } from '@playwright/test';
export default defineConfig({
testDir: './tests',
fullyParallel: true,
reporter: 'list',
use: {
baseURL: process.env.BASE_URL ?? 'http://127.0.0.1:3000',
browserName: 'chromium',
headless: true,
viewport: { width: 1440, height: 1000 },
deviceScaleFactor: 1,
locale: 'en-IN',
timezoneId: 'Asia/Kolkata',
colorScheme: 'light',
reducedMotion: 'reduce',
trace: 'retain-on-failure',
},
expect: {
toHaveScreenshot: {
animations: 'disabled',
caret: 'hide',
// Leave diff tolerances at their defaults until you have reviewed
// real diffs and understand which rendering variation is harmless.
},
},
});
Set BASE_URL to your local or test deployment. Make sure test data, product content, and assets are available and stable before creating reference images. If you launch the application from Playwright, add a webServer configuration; its options are documented in the Playwright webServer guide.
2. Write a product-page visual test
This example assumes the product page has a stable URL and accessible names for its controls. Replace the URL, selectors, and expected content with those from your storefront. It checks the initial product state, selects another variant, and compares both the full page and a focused product summary. The focused assertion is optional: keep it when a localized diff helps reviewers understand a failure.
import { test, expect } from '@playwright/test';
test('product page default and selected variant', async ({ page }) => {
await page.goto('/products/cotton-shirt', { waitUntil: 'domcontentloaded' });
// Assert behavior and content separately from the visual comparison.
await expect(page.getByRole('heading', { name: 'Cotton Shirt' })).toBeVisible();
await expect(page.getByTestId('price')).toHaveText('₹1,499');
await expect(page.getByRole('button', { name: 'Add to cart' })).toBeEnabled();
// Wait for app data and images that matter to the product area.
await expect(page.getByTestId('product-gallery')).toBeVisible();
await expect(page.getByTestId('product-image').first()).toHaveJSProperty('complete', true);
await expect(page).toHaveScreenshot('cotton-shirt-default.png', {
fullPage: true,
});
await expect(page.getByTestId('product-summary')).toHaveScreenshot(
'cotton-shirt-summary-default.png',
);
await page.getByRole('button', { name: 'Choose size M' }).click();
await expect(page.getByRole('button', { name: 'Choose size M' })).toHaveAttribute('aria-pressed', 'true');
await expect(page.getByTestId('price')).toHaveText('₹1,499');
await expect(page).toHaveScreenshot('cotton-shirt-size-m.png', {
fullPage: true,
});
});
toHaveScreenshot() waits until two consecutive screenshots produce the same result and compares the final capture with the stored expectation. That stabilization helps with transient rendering, but it does not make arbitrary page data deterministic. Freeze or control changing content, wait for important application state, and avoid capturing while a carousel, stock ticker, or personalization widget is moving.
Run it and create the first baseline
npx playwright test
The first run creates expected screenshots. Review them as test artifacts before treating them as trusted references. Commit approved snapshots with the test code so reviewers can see when a reference changes. On later runs, Playwright compares captures against those references and reports visual differences.
To intentionally refresh expectations after reviewing a design or content change, run:
npx playwright test --update-snapshots
Review the resulting image changes in version control. Updating snapshots is not a way to make a failing test pass without understanding the diff.
3. Choose product states and comparison scope
A product page is a collection of states, not one screenshot. Choose a small set that reflects the user journeys and risks your team needs to protect. The following is a practical test-design recommendation, not a Playwright-prescribed ecommerce matrix.
| State or area | What to capture or assert |
|---|---|
| Default product | Title, primary image, default variant, price, stock status, and purchase controls. |
| Another variant | Selection styling, SKU or image changes, price changes, and availability. |
| Unavailable item or variant | Out-of-stock message, disabled purchase action, and any alternative action. |
| Delivery or pincode result | Delivery estimate, serviceability status, and validation or error state. |
| Long details | Full-page layout, product description, specifications, and applicable declarations. |
| Responsive layout | At least the viewports your design supports and your customers use. |
Use full-page screenshots when page-wide layout, spacing, or content flow is the risk. Use a locator screenshot for a gallery, price block, variant selector, or purchase panel when a focused image makes review easier. Long full-page captures can take more time to inspect and may expose dynamic sections, so choose the scope that answers the question behind the test.
For each screenshot state, assert the important content and behavior directly as well. For example, check that the selected size is actually selected, the displayed price matches the fixture, the delivery result corresponds to the entered pincode, and the cart action works. A visual diff is a detection signal, not a semantic explanation.
4. Keep screenshots stable and useful
Rendering can vary with operating system, browser version, browser settings, hardware, power source, and headless mode. Generate and compare baselines in the same environment wherever possible. Pin dependency versions, use the same browser project and operating system in CI, and keep fonts and test data consistent. Playwright’s visual comparisons guide describes these sources of rendering variation and its snapshot workflow.
- Control data: use fixtures or a test catalog with fixed prices, inventory, product images, and delivery outcomes. Avoid live production pages whose content can change between runs.
- Wait for meaningful readiness: wait for the product heading, price, gallery, and any state-specific result. The screenshot assertion waits for stable screenshots, but your test must still ensure the app has loaded the intended state.
- Handle animation: the configuration above disables animations for screenshot assertions and requests reduced motion. If animation itself is under test, write a separate behavior test rather than depending on a random animation frame.
- Hide only irrelevant volatility: Playwright screenshot options can mask selected locators or apply a style. Do so narrowly for values such as a deliberately changing timestamp. Do not mask prices, stock, or other content whose correctness matters.
- Choose tolerances carefully: screenshot options include
maxDiffPixels,maxDiffPixelRatio, andthreshold. A looser tolerance can conceal a meaningful regression. Start strict, inspect recurring noise, then adjust only with a documented reason. - Check images and fonts: ensure product assets and web fonts have loaded. Missing assets can produce a stable but incorrect baseline. If image completeness is not exposed on your page, wait on the application’s own loaded state or use a suitable locator and assertion.
See the official PageAssertions API reference for screenshot assertion behavior and available options. The exact options should be checked against the Playwright version pinned by your project.
5. Include India-specific listing checks where applicable
For pre-packaged commodities, the Department of Consumer Affairs’ overview of the Legal Metrology (Packaged Commodities) Rules, 2011 describes declarations that can include manufacturer, packer, or importer name and address; country of origin for imported products; common or generic product name; net quantity; manufacture month/year; best-before or use-by information for commodities that may become unfit; MRP inclusive of taxes; consumer-care details; applicable dimensions; and unit sale price. Applicability depends on the product and the governing rule. Treat this as a review checklist, not a conclusion that every field applies to every listing. Consult current official material and category-specific rules. See the [Department of Consumer Affairs overview](https://consumeraffairs.nic.in/acts-and-rules/legal-metrology).
Where those details appear on the page, test them as content as well as reviewing their visual presentation. For example, keep a fixture with the expected origin and net quantity, assert the relevant text, and capture the details section so a layout change does not hide it.
A 2026 amendment specifies that, from July 1, 2027, ecommerce entities offering imported products must provide a searchable and sortable product-listing filter specifying country of origin. As of October 2026, this is a future effective requirement. Plan an appropriate listing-page behavior test and visual state if it applies to your product; do not represent it as already effective. Refer to the [official amendment](https://consumeraffairs.nic.in/sites/default/files/Legal%20Metrology%20%28Packaged%20Commodities%29%20Second%20Amendment%20Rules%2C%202026.pdf) and current rules for the authoritative wording.
The government’s [Press Information Bureau explanation of the 2017 amendment](https://pib.gov.in/PressReleasePage.aspx?PRID=1484275) discusses declarations for goods displayed by sellers on ecommerce platforms and MRP context. Check current legal text before making compliance decisions; an automated visual test cannot determine whether a declaration is legally required for a particular item.
6. Run visual checks in CI and review diffs
Run the same Playwright command in CI for relevant frontend changes. Use a consistent runner image and browser installation, and make sure the checked-out baseline files are available to the job. A failed screenshot assertion should leave a diff and actual image that the team can inspect. With trace: 'retain-on-failure', Playwright also retains a trace on failure for investigation.
- Open the expected, actual, and diff images for the failing state.
- Check whether the change is intended, a content or fixture change, an environment mismatch, or a regression.
- Use functional assertions and the test trace to understand the page state behind the pixels.
- If the change is intentional, update the baseline in a reviewed change and commit the new expected image with the code or content change.
- Run the test again in the baseline environment to confirm the reviewed expectation is stable.
Keep snapshot changes visible in code review. Avoid bulk baseline updates without examining them: a mass update can silently accept a real layout regression. The Playwright documentation describes storing snapshots alongside tests and updating them with --update-snapshots.
7. Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| Screenshot differs on every run | Dynamic data, animation, rotating content, a changing date, or inconsistent rendering environment. | Use fixed fixtures, wait for the intended state, disable irrelevant animation, and align browser, OS, fonts, and viewport with baseline generation. |
| First run passes but later CI runs fail broadly | Baseline was generated on a different browser or operating system, or dependencies changed. | Generate and compare in the same pinned CI environment; review whether a browser update warrants a deliberate baseline refresh. |
| Product image is blank in the capture | Capture happened before the asset loaded, the test environment cannot reach the asset, or the fixture points to a missing file. | Check the image request and fixture, wait for the app’s loaded state, and ensure the asset is available in CI. |
| Capture shows a loading skeleton | The app’s data request is still pending, or the test did not wait for the requested product state. | Wait for a state-specific element or response outcome rather than relying only on a generic navigation event. |
| Unexpectedly large diff after a small CSS edit | A shared style, font, viewport, or layout change affected many regions. | Inspect the diff by region, check computed layout and loaded fonts, and decide whether the wider change is intended before updating snapshots. |
| Small antialiasing differences cause failure | Rendering differs across environments or the test uses a tolerance that is too strict for the pinned setup. | First align environments. If residual noise is understood and harmless, adjust a documented threshold or pixel tolerance narrowly. |
--update-snapshots changes many files |
The command refreshed every affected expectation, possibly because of an environment or broad design change. | Do not accept the batch blindly. Compare the diffs, identify the common cause, and split intentional changes from unintended ones. |
| Text assertions pass but the screenshot fails | The content is correct but styling, spacing, visibility, or asset presentation changed. | Review the actual and diff images; use a locator screenshot if the full page obscures the affected component. |
| Screenshot looks correct but a user flow is broken | Pixels do not prove that controls, navigation, or backend state work. | Add interaction and URL assertions, and test cart, variant, stock, and delivery behavior independently. |
8. Performance, reliability, and cost
Visual checks add browser rendering and image comparison work to a test suite. Keep the suite focused on representative page states instead of multiplying nearly identical captures. Component screenshots can make diffs quicker to inspect; full-page captures cover layout risks but produce larger images. Run checks in parallel only to the extent your CI resources and test data support it. Shared mutable inventory or sessions can undermine determinism.
For reliability, use controlled data and assets, pin the browser environment, retain useful failure artifacts, and make baseline updates reviewable. A screenshot pass says that the rendered pixels stayed within the configured comparison rules for that environment; it does not guarantee correctness across every device, browser, product, or legal requirement.
Playwright Test is an open-source test runner; the dossier provides no paid service price or performance benchmark to cite. Your practical cost is the CI capacity and engineering time needed to capture, inspect, and maintain tests. No defect-reduction or conversion figure is established by the available sources.
9. Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server. It can capture a URL as PNG, JPEG, WebP, or PDF. For a product page, a minimal API call looks like this; see the ScreenshotNeo API docs for the request options.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
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)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
Replace the example URL with your product page. ScreenshotNeo removes cookie banners, popups, and chat widgets before the shot; each cleanup step can be turned off. Bot checks, blank pages, and failed loads are never billed, and response headers report the page verdict and billing status. Its MCP server gives AI agents tools to take screenshots, get page information, and capture PDFs. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 shots. Plans include every feature. For a comparison workflow, save captures from the same URL and state, then review them against your approved references; the Playwright assertions above remain useful for automated pass/fail checks in your test suite.
Sign up for 1,000 free screenshots a month, with no card required.
10. Frequently asked questions
Does a screenshot comparison prove a product page is correct?
No. It detects rendered changes against a reference. Add assertions for content and behavior, and review whether each visual change is intended.
Should every product have its own baseline?
Use representative fixtures and states that cover meaningful differences. Avoid duplicating captures for products that render identically unless product-specific content or layout is itself a risk.
Can I use a live Indian ecommerce product URL as the baseline?
You can navigate to a URL, but live pages can change content, availability, prices, and assets independently of your code. A controlled test environment is usually easier to compare reliably.
When should I update a snapshot?
After confirming the visual change is intentional and reviewing the new capture. Keep the baseline change in the same reviewed change as the product update when practical.
Does the packaged-commodity declaration checklist apply to every online product?
No. The listed declarations concern packaged commodities and applicability depends on the product and current rules. Confirm the applicable requirements from official sources for the specific category.


