how to implement comparing two screenshots in one test with playwright

4.6k Views Asked by At

I am very new to playwright and i have a problem. I am trying to implement comparing two screenshots (before and after) in one test. this is what i want to achieve:

  1. navigate to webpage
  2. take screenshot (before.png)
  3. do some stuff,state changes, etc
  4. take screenshot (after.png)
  5. compare before.png to after.png (if they are the same test should pass, otherwise test fails)

something like this:

test('compare screenshots', async ({ page }) => {
  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`
  })
  expect(beforeImage).toMatchSnapshot(afterImage)
});

but it does not work like this. Any ideas/suggestions how can i achieve this? Help would be greatly appreciated

2

There are 2 best solutions below

0
Basti On

You can do something like this:

test('compare screenshots', async ({ page }, testInfo)=>{
  await page.goto(pageUrl);
  const screenshotTarget =  page.locator(scTarget);
  await expect(screenshotTarget).toHaveScreenshot( `${testInfo.title}.png`);
  //
  // some state changes implemented here
  //
  await expect(screenshotTarget).toHaveScreenshot( `${testInfo.title}.png`);
});

I prefer to use the test titel for naming my screenshots but it should also work if you just enter the same name twice. Then if you run your tests without --update-snapshots they should fail if some visual changes happened.

4
d2vid On

The problem with Playwright's toHaveScreenshot and toMatchSnapshot is that they're a bit over-engineered and will only compare a current screenshot to a screenshot from a previous test run. 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).