Intro

In my last post, I talked about how to get started with visual testing using Playwright. In this post, I’m going to cover how to handle dynamic data in your visual tests.

What is dynamic data?

For the purposes of this post, I’m defining dynamic data as anything on your web page that could change between test runs. This could be data that is generated randomly, data that is pulled from an API, data that is based on the current date or time, etc.

Options for dealing with dynamic data

In visual testing, it’s essential to ensure that tests are consistent and reliable. When applications contain dynamic data, a decision is needed on how to handle it within the visual tests.

Option 1: Mock your dynamic data

One option for handling dynamic data in your visual tests is to mock the data so that it is consistent each time you run the test. For example, if you have a list of items that can change over time (and break you test), you could mock the list so it’s the same each time you run the test.

Option 2: Hide the dynamic data

Another option for handling dynamic data in your visual tests is to hide the data so that it is not visible in the screenshot. This is the option I’m going to focus on in this post, as it can be a simple and effective way to handle dynamic data in your visual tests.

Back to my sample application

In my last post I had a sample ToDo app with a single Playwright visual testing. I’ve tweaked the application to include the current date and time in the footer. So now when I run the test it fails, because it doesn’t match my baseline image:

Image description

You can see the Actual page has the current date and time in the footer, but the Baseline image does not. You can also look at the Diff image to see the highlighted differences between the two:
Image description

Hiding dynamic data

The toHaveScreenshot() function in Playwright is what we use to do the screen shot comparison, and it accepts a stylePath parameter that allows you to hide elements on the page before taking the screenshot. This is a great way to handle dynamic data in your visual tests. In my sample application I created screenshot.css that looks like this:

1
2
3
#datetime {
display: none;
}

I then pass this file to the toHaveScreenshot() function like this:

1
2
3
4
5
await expect(page).toHaveScreenshot(
[os.platform(), 'landing.png'],
{
stylePath: path.join(__dirname, 'screenshot.css'),
});

Now when I run the test, the dynamic data is hidden, and the test passes. The Baseline image does not need to change, as the dynamic data is not visible in the screenshot.

Masking dynamic data

Another option for dealing with dynamic data is to use Playwright’s mask parameter, like this:

1
2
3
4
5
6
7
await expect(page).toHaveScreenshot(
[os.platform(), 'landing.png'],
{
mask: [
page.locator('#datetime')
]
});

If you what to go this route, you would need to update the Baseline image to include the mask. This is a little more work, but it’s a good option if you want a placeholder for the dynamic data in the Baseline image:

Image description

But what if hiding dynamic data is also hiding a bug?

Hey, great question! The good news is you still have the ability to do functional validation of that dynamic data, just like you always have.

For example, if I want to verify datetime is displayed and it matches the current date, I could just do something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const datetimeValue = page.locator('#datetime-value');

// Verify that the datetime value element is visible
await expect(datetimeValue).toBeVisible();

// Get the text content of the datetime value element
const datetimeText = await datetimeValue.textContent();

// Check if datetimeText is a valid date string
if (datetimeText && !isNaN(Date.parse(datetimeText))) {
const datetimeDate = new Date(datetimeText).toLocaleDateString();
const currentDate = new Date().toLocaleDateString();

// Assert that the date part of the datetime value is equal to the current date
expect(datetimeDate).toBe(currentDate);
} else {
throw new Error('Invalid datetime text');
}

This code verifies the datetime is displayed, and it’s the current date. I can then let my visual comparison do the rest of the heavy lifting.

Wrap-up

So that’s about it for this post. You now know how to hide dynamic data in your visual tests, as you continue using functional validation to ensure the dynamic data is correct.

So far these blog posts have been focused on how Playwright supports visual testing, without considering cloud-based solutions like Applitools or Percy. In my next post I’ll cover how to integrate Playwright with Applitools (or Percy) for visual testing. Stay tuned!