What is a good way to make screenshot tests with Playwright?

6.4k views Asked by At

What is the good way to make a screenshot test with playwright?

If I understand truly, I need to make screenshot, like below:

it('Some test', async () => {
    page.screenshot({ path: 'screenshot.png' });
}

But how I can to compare it with etalon screenshots? If I missed something in the docs, lets me know, please

2

There are 2 answers

1
ZoomAll On

judging by the fact that the Playwright team started developing their own test runner which can compare screenshots:

playwright-test#visual-comparisons

import { it, expect } from "@playwright/test";

it("compares page screenshot", async ({ page, browserName }) => {
  await page.goto("https://stackoverflow.com");
  const screenshot = await page.screenshot();
  expect(screenshot).toMatchSnapshot(`test-${browserName}.png`, { threshold: 0.2 });
});

they do not plan to add such functionality directly to the Playwright

1
d2vid On

Playwright's toHaveScreenshot and toMatchSnapshot are great if you want to compare a current screenshot to a screenshot from a previous test run, but if you want to compare two screenshots that you have as Buffers in memory you can use the getComparator method that Playwright uses behind the scenes:

import { getComparator } from 'playwright-core/lib/utils';

await page.goto('my website here');
const beforeImage = await page.screenshot({
    path: `./screenshots/before.png`
});
//
// some state changes implemented here
//
const afterImage = await page.screenshot({
  path: `./screenshots/after.png`
});

const comparator = getComparator('image/png');
expect(comparator(beforeImage, afterImage)).toBeNull();

The advantage of using getComparator is that it fuzzy matches, and you can set the threshold of how many pixels are allowed to be different. If you just want to check that the PNGs are exactly identical, a dead simple method to check for equality between the two screenshots is:

expect(Buffer.compare(beforeImage, afterImage)).toEqual(0)

Beware though - this simpler method is flakey and sensitive to a single pixel difference in rendering (such as if any animations/transitions are not completed or if there are differences in anti-aliasing).