Sponsored Link
Looking for a unified way to  viewmonitor, and  debug Playwright Test Automation runs?
Try the Playwright Dashboard by today. Use the coupon code PWSOL10 for a 12 month 10% discount.

Playwright Solutions Challenge: Debug and figure out why the video recording isn't in the HTML report?

A few weeks back I was approached with a playwright challenge. The challenged seemed like an easy one to solve but I was surprised with the solution, so much so I wanted to share it here and give you a chance to exercise your debug skills.

The Challenge

🎯
The Challenge: Populate the video recording in the HTML Report

An example repo can be found below. Clone/download the repo down with git clone https://github.com/playwrightsolutions/playwright-solutions-challenges.git

Once pulled down run npm install in the main directory, and if you don't have playwright browsers installed you may need to run npx playwright install.

GitHub - playwrightsolutions/playwright-solutions-challenges: A repo with different Playwright Challenges
A repo with different Playwright Challenges. Contribute to playwrightsolutions/playwright-solutions-challenges development by creating an account on GitHub.

Once you have everything installed run

npx playwright test

This will run 1 test, which will fail, and you should have access to the html report which will have a screenshot of the failure, a trace viewer file of the failure but no video.

Take some time and attempt to solve this challenge. Here is some nice relaxing music to help time box your self to.

Have you solved it? Scroll below to see the solution.

Alright hopefully you attempted to solve the problem or at least inspected the code. My first instinct was to check the playwright.config.ts file which when looking everything looked good. The original example actually had a lot more code in the test, which made the error really easy to over look, so my next step in debugging was to actually check out the official playwright documentation and implementation.

I created a new directory and installed playwright from scratch via npm init playwright@latest. I enabled video in the playwright config, I then copied and pasted the bulk of the test within the test block over and run the test and whalla I had a video recording.

This led me to further inspect the Playwright test file and specifically the beforeEach block. Here is where the issue lies.

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

let page: Page;

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

test.describe("Swag Labs Tests ", () => {
  test("Login checks", async ({}) => {
    await page.goto("https://www.saucedemo.com/");
    await page.fill('[data-test="username"]', "standard_user");
    await page.fill('[data-test="password"]', "secret_sauce");
    await page.click('[data-test="login-button"]');
    await page.getByRole("button", { name: "Open Menu" }).click();
    await expect(
      page.locator('[data-test="logout-sidebar-link"]')
    ).toBeVisible();
    expect(page.url()).toBe("https://www.saucedemo.com/inventory.html");
    expect(1).toBe(2);
  });
});

The Solution

The issue is we are creating a new variable named page and not using the page that the playwright test framework provides. The import test gives you access to page you just have to pass it into the test block in order to use it. If you were using Playwright Library by itself without the test runner, this step would be necessary in order to create a browser context. But when using Playwright Test you have access to the page fixture by default. You can read more about it in the first section of the Fixture Docs. The page fixture is one of the pre-defined fixtures that are always available when using Playwright Test.

I ended up removing the Page from the import block, I removed the beforeEach() block, and I am now passing in ({ page }) within the test block. This will give me access to the page that Playwright Test builds for me by default.

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

test.describe("Swag Labs Tests ", () => {
  test("Login checks", async ({ page }) => {
    await page.goto("https://www.saucedemo.com/");
    await page.fill('[data-test="username"]', "standard_user");
    await page.fill('[data-test="password"]', "secret_sauce");
    await page.click('[data-test="login-button"]');
    await page.getByRole("button", { name: "Open Menu" }).click();
    await expect(
      page.locator('[data-test="logout-sidebar-link"]')
    ).toBeVisible();
    expect(page.url()).toBe("https://www.saucedemo.com/inventory.html");
    expect(1).toBe(2);
  });
});

This got me thinking, I don't think this problem would have been as easy for me to identify or solve without knowing about the goodies that Playwright provides out of the box. This came from reading the Playwright Docs, which is something I always encourage folks to do, there is a plethora of knowledge awaiting you!

Another solution

Let's say you don't want to use the built in filter. Another option would be to set the video settings within the browser context. Here is a link to a response from one of the Playwright development team members Max - https://github.com/microsoft/playwright/issues/14164#issuecomment-1131451544

This is the work around he provided implemented

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

let page: Page;

test.beforeEach(async ({ browser }, testInfo) => {
  page = await browser.newPage({
    recordVideo: {
      dir: testInfo.outputPath("videos"),
    },
  });
});

test.afterAll(async ({}, testInfo) => {
  const videoPath = testInfo.outputPath("my-video.webm");
  await Promise.all([page.video().saveAs(videoPath), page.close()]);
  testInfo.attachments.push({
    name: "video",
    path: videoPath,
    contentType: "video/webm",
  });
});

test.describe("Swag Labs Tests ", () => {
  test("Login checks", async ({}) => {
    await page.goto("https://www.saucedemo.com/");
    await page.fill('[data-test="username"]', "standard_user");
    await page.fill('[data-test="password"]', "secret_sauce");
    await page.click('[data-test="login-button"]');
    await page.getByRole("button", { name: "Open Menu" }).click();
    await expect(
      page.locator('[data-test="logout-sidebar-link"]')
    ).toBeVisible();
    expect(page.url()).toBe("https://www.saucedemo.com/inventory.html");
    expect(1).toBe(2);
  });
});

Did you find another way to solve this challenge? I'd love to hear from you reach out to me on LinkedIn with the details!


Thanks for reading! If you found this helpful, reach out and let me know on LinkedIn or consider buying me a cup of coffee. If you want more content delivered to you in your inbox subscribe below, and be sure to leave a ❤️ to show some love.