How to test cookies using end-to-end tests and Playwright

Cookies are a vital part of any website, not only for tracking purposes but for core functionalities too. It’s AB tests, personalization, or any feature that needs to preserve some visitor-specific data. How can you test the cookie-based functionality using Playwright?

Ondrej Polesny

Published on Mar 15, 2023

In this article, I’ll explain what end-to-end testing is, where it lies in automated testing processes, how to execute it using the testing framework Playwright, and how it can be used to verify cookie-based functionalities of your site.

What is end-to-end (E2E) testing?

An end-to-end test is a final check that a feature is working. If you look at the testing pyramid, E2E tests are at the top above unit (single feature test) and integration (testing how modules fit together) tests as they check how the entire system works. In a website environment, you execute them on a running website, typically on localhost or on a preview version built during the deployment process.

Diagram showing the CI and manual run of E2E tests.

These are a few examples of how we use E2E tests to verify the functionalities of this site:

  • When functional UTM parameters are used, they are always added to cookies
  • Form validation on specific pages requires a company email address
  • The homepage has all the required Twitter and SEO tags
  • Visiting a specific landing page adds extra data to cookies
  • Analytical cookies are stored in a visitor’s browser only when they allow it
  • Form requests contain all required data by the target system (including request interception)

What is Playwright?

In the diagram above, I’ve already used Playwright – a testing framework that enables reliable end-to-end testing for modern web apps. It allows us to run these tests locally as well as in a serverless environment, for example, as part of your deployment process.

How does end-to-end testing with Playwright work?

In order to run the end-to-end tests with Playwright, you need to install the NPM package, including the Playwright browser binaries. Locally, you need to do this once and upgrade the package version should you need to test using the latest browsers. In the scope of the deployment process, you typically install Playwright and its dependencies as a pre-requisite, so you always use the latest binaries.

Then, you run your website and tell Playwright the URL. The rest is up to the testing framework. We do it using GitHub Action – I explained the whole process in my previous article. Here, I’ll focus only on the Playwright part:

npm ci
npx playwright install --with-deps
npm run test:e2e

Note: Playwright requires a baseURL to know where to execute the tests. In remote environments, you typically use a project environment variable that you assign according to the used environment.

Why you should test cookies with Playwright

We started using Playwright for testing cookies with the Syntax.fm podcast sponsorship. We wanted to create a special offer for podcast subscribers and needed to have a new landing page with a very simple URL. An URL that anyone listening to the podcast can easily remember. In order to claim the offer, we needed to store a special cookie on the visitor’s browser when they visited the page:


Cookies.set('utm_source', 'syntaxfm', { expires: 7, domain: '.kontent.ai'})
Cookies.set('utm_medium', 'podcast', { expires: 7, domain: '.kontent.ai' })
Cookies.set('utm_campaign', 'extended_trial', { expires: 7, domain: '.kontent.ai' })

The code above is a bit simplified as there’s more dynamicity in how we obtain the domain and cookie parameters’ values. Therefore, we needed to be certain that:

  • These cookies are always added to the visitor’s browser regardless of the cookie consent – these cookies are functionally necessary for claiming the offer
  • The cookie has a specific value that is expected by the app when the user registers

How to test cookies using Playwright

The test looks like this:

await page.goto('/syntax')
const cookies = await context.cookies()
await expect(cookies.find(c => c.name == 'utm_source').value).toBe('syntaxfm')
await expect(cookies.find(c => c.name == 'utm_medium').value).toBe('podcast')
await expect(cookies.find(c => c.name == 'utm_campaign').value).toBe('extended_trial')

First, we instruct Playwright to go to the new landing page /syntax and wait for its browser to process the page. Then, when we have cookies available, we use the expect function to verify that the browser stored those three important cookies.

This way, we know that whenever the E2E tests pass, the page stores the needed cookies properly.

Now, this test is specific to checking only the technically necessary cookies. Should you need to test the presence of cookies that are pure analytics/marketing, you can instruct Playwright to accept or deny them using a button click:

// wait for the cookie consent to appear
await page.$$('button:has-text("Allow all cookies")')
// click on the button
await page.click('button:has-text("Allow all cookies")')

const cookies = await context.cookies()
...

Note: We are locating the "Allow all cookies" button based on its label, but you may use any other locator that fits you better.

Conclusion

In this article, I explained what the Playwright testing framework is, showed how it works, and how it can be integrated into the scope of every deployment. Then, I shared our experience with testing the essential and non-essential cookies and explained why it’s beneficial to have an E2E test covering these scenarios.

If you are new to Playwright and end-to-end testing or simply want to discuss your project details, make sure to join the Kontent.ai community on Discord.

Feeling like your brand’s content is getting lost in the noise?

Listen to our new podcast for practical tips, tricks, and strategies to make your content shine. From AI’s magic touch to content management mastery and customer experience secrets, we’ll cover it all.

Kontent Waves

Subscribe to the Kontent.ai newsletter

Stay in the loop. Get the hottest updates while they’re fresh!