(Updated: )

Why didn't my Playwright test capture video?

Share on social

CCD camera image By Hannes Grobe - Own work, CC BY-SA 4.0, https://commons.wikimedia.org/w/index.php?curid=99514758
Table of contents

tl;dr: you won’t capture video of a test if you use browser.newContext() or if you reuse a Page type in multiple tests. This is a known Playwright issue. Fixtures can provide a similar function.

If you use Checkly, eventually you'll be looking at alerts about something failing, and wonder how to debug a failed check. For most of us, the first thing we want to see is the video of a failed check run. Sometimes, though, our check doesn’t capture video. This guide will cover three common reasons a video doesn’t show up on a check run. This advice is general for Playwright as well as those running Playwright tests on Checkly.

Videos aren’t recorded on successful runs

This is also in a tooltip on the Checkly dashboard but: Checkly doesn’t record video of successful runs. Hopefully you have many thousands more successful runs than failures! If you’re running playwright tests locally, you can configure successful runs to still record video.

Can’t record video from multiple browsers: browser.newContext()

The last two common failure modes are both the result of the same limitation, but since they have rather different code and test needs we’ll cover them in two sections. Firstly, using browser.newContext() means there’s no longer a single browser page to gather video.

In this example, we’ll use browser.newContext() twice to have a context for the user view and the admin view for our e-shop.

const { expect, test } = require('@playwright/test')

test(`ordering a book`, async ({ browser }) => {
  //one Context for the user
  const userContext = await browser.newContext();
  const userPage = await userContext.newPage();
  const response = await userPage.goto('https://danube-webshop.herokuapp.com/')
  await userPage.getByLabel('order').click();

  const adminContext = await browser.newContext();
  //use the admincontext to check that the book was ordered

  // Test that the response did not fail
  expect(response.status(), 'should respond with correct status code').toBeLessThan(400)
})

This is a functional test but it won’t gather video!

However you run this test, if you check either the Checkly dashboard or the native playwright test reporter, no video will be captured. Why not? I compare it a bit to the requirement to use .first() with a locator when more than one item matches the locator: your instructions have left Playwright in an unclear state. Playwright captures video by following a page from start to finish through a test run. When you create a new context it’s not clear which page should be captured.

Can’t record across multiple tests: re-using page across tests

Did you know you can run multiple tests inside a single Checkly check? You totally can! This check has two separate tests giving separate results on the report:

reused-page.spec.ts
import { test, expect, type Page } from '@playwright/test';

test.describe.configure({ mode: 'serial' });
let page: Page;

test.beforeAll(async ({ browser }) => {
  page = await browser.newPage();
});

test.afterAll(async () => {
  await page.close();
});

test('right book genre', async () => {
  await page.goto('https://danube-webshop.herokuapp.com/');
  await page.getByText('Celsius').click();
  await expect(page.locator('#app-content')).toContainText('Genre: scifi');
});

test('one book in stock', async () => {
  await expect(page.locator('#app-content')).toContainText('Left in stock: 1');
});

When we run this check in Checkly, we get two separate test traces, and both tests have to pass for this check status to be green. However you might notice something missing from the check report:

Checkly edit check tool showing a successful check run, with two separate tests within one check run

While these tests didn’t capture video, we can fix that!

Sure enough there’s no videos on these tests.

The issue is a bit of cleverness in this test setup. The test author didn’t want to have to navigate around to the right page for each test, so instead she created a Page and used the same page in both tests:

//Since 'right book genre' does the first navigation, 
//we need to make sure our tests run in sequence
test.describe.configure({ mode: 'serial' });
let page: Page;

test.beforeAll(async ({ browser }) => {
  page = await browser.newPage();
});

test.afterAll(async () => {
  await page.close();
});

The same page gets used in both of these tests. Once again the underlying issue is that Playwright only captures video for a single page running over the course of a single test. The nature of the failure is a bit different: rather than multiple pages in one test, now a single page stretches across multiple, but the result is the same.

Note: Unrelated to video capture, while the code above saved a few lines of repeated code, it also required tests to be run in sequence, and broke the independence of tests, and as such is an antipattern for most teams.

The rewrite of this test to not use one page across two tests is quite simple, we just have to accept that a few lines will be repeated:

import { test, expect, type Page } from '@playwright/test';

test('right book genre', async ({page}) => {
  await page.goto('https://danube-webshop.herokuapp.com/');
  await page.getByText('Celsius').click();
  await expect(page.locator('#app-content')).toContainText('Genre: scifi');
});

test('one book in stock', async ({page}) => {
  await page.goto('https://danube-webshop.herokuapp.com/');
  await page.getByText('Celsius').click();
  await expect(page.locator('#app-content')).toContainText('Left in stock: 1');
});

How to fix video capture for Playwright tests

While the problem is solved for the test above by repeating a few lines of code, how do we generalize a solution to page reuse or multiple contexts in one test? At bottom, our motivation in both these cases was DRY (don’t repeat yourself) code. These techniques made it easier to test multiple scenarios without copy-pasting the same code block several times. What’s the general solution? Fixtures!

In either example above, a fixture to carry out repeated tasks can achieve the same DRY design while still grabbing video as expected.

To see test fixtures in action, check out Stefan's video on reusing code across Playwright tests with fixtures:

Share on social