Playwright provides a fast and reliable interface that can be used to automate browser navigation testing.

In this Playwirght tutorial, we are going to use it to do some simple automated test and errors you might experience in the process.  

See the following Github repository:

GitHub - KarmaComputing/playwright-testing
Contribute to KarmaComputing/playwright-testing development by creating an account on GitHub.

The Karmacomputing/playwright-testing is based on three tests with some main configuration.

The test will consist of playwright going to https://herbivorehacker.subscriby.shop/ and https://footballclub.subscriby.shop/ but before redirecting to any of those web addresses it first navigate to https://subscriptionwebsitebuilder.co.uk. This is to demonstrate that a Playwright test does not have to be tied to one domain, entire browser sessions may be automated/tested.

The test will be tested in two different scenarios: -

  • Desktop Browser in Chrome
  • Mobile Browser

Both tests will run in parallel to make the test faster.

A common browser automated testing problem is waiting until a page or element is loaded: every site has a different time to load and different elements load (loading will depend on the network connection at the time of the request).

In this case: https://subscriptionwebsitebuilder.co.uk/ has an element that is loaded at the end which will be discussed later.

First, we are going to talk about the configuration steps.

Playwright global configuration file:

By default, playwright/test reads the filed called playwright.config.js to use as a global configuration file. You can use a different name for the config file but you will have to specify the path to it.

Inside the configuration file are the settings that we don't want to repeat all over in every test file that we want to do.

playwright.config.js example:

const { devices } = require('@playwright/test');

/** @type {import('@playwright/test').PlaywrightTestConfig} */
const config = {
  workers: 2,
  retries: 2,
  use: {
    headless: false,
    viewport: { width: 1280, height: 720 },
    launchOptions: {
      slowMo: 1000,
    },
    video:"on",
    },
  projects: [
    {
      name: 'Desktop Chromium',
      use: {
        browserName: 'chromium',
      },
    },
    // Test against mobile viewports.
    {
      name: 'Mobile Safari',
      use: devices['iPhone 12'],
    },
  ],
};

module.exports = config;

In this test we define two projects:

  • Desktop browsing using chromium  
  • Mobile browsing simulating Mobile safari.

Therefore, we are going to use two workers. Why? because we want to run the mobile and desktop test in parallel to save time since both will be testing the same.

We are going to setup 2 tries in case a test failed it can retry again one more time.

By making "headless: false" we are going run the test by default to open the browser- so that we can see what's happening. If you want to to change it to true then you will have to use

npx playwright test --headed

To record videos of the test we can adjust the resolution to 720p, make the video slower by enabling slowMo to 1 second and turn video:'on'.

Now for the general test we are going to add this to the file foo.spec.js

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

//two test example
test.describe("tests:", () => {
  test.beforeEach(async ({ page }) => {
  // Go to the starting url before each test.
    await page.goto('https://subscriptionwebsitebuilder.co.uk/');
    const name = await page.innerText('.navbar-brand');
    expect(name).toBe('Subscribie');
    await page.isVisible('.tawk-text-truncate');
    await page.isVisible('.tawk-icon-right');
    await new Promise(x => setTimeout(x, 1000));
    expect(await page.screenshot()).toMatchSnapshot('subscribie.png');
  });

  test("navigating to footballclub", async ({ page }) => {
    await page.goto('https://footballclub.subscriby.shop/');
    const name = await page.innerText('.title-1');
    expect(name).toBe('Football Club');
    expect(await page.screenshot()).toMatchSnapshot('football-subscribie.png');
  });

  test("navigating to herbivorehacker", async ({ page }) => {
    await page.goto('https://herbivorehacker.subscriby.shop/');
    const name = await page.innerText('.title-1');
    expect(name).toBe('Herbivore Hacker');
    expect(await page.screenshot()).toMatchSnapshot('herbivore-subscribie.png');
  });

});

In this test file, remember, we are going to do two tests but before each test it will be redirected to https://subscriptionwebsitebuilder.co.uk/ as an example. This is why the test has an attribute called ".beforeEach".

The first redirection its the harder part of the test. why? Because https://subscriptionwebsitebuilder.co.uk/ loads an online chat widget element (tawk) at the end so the test will need to wait for the tawk element to load before it takes the screenshot.

In playwright test the screenshots can be handled in a different but useful way. The ".toMatchSnapshot" takes a first screenshot at the beginning of the first test to match it with the other tests and compare them.  

The test can fail if the first screenshot does not reassemble the first snapshot which is why we need to check for the last element loaded before taking a screenshot. Once we visit the site and know the last element that is being loaded in the website then we can target it by class, id, or text using the inspect tools of the preferred browser.

Playwright css selection tips:

  • class names are defined with a  "." , for example (".tittle-1")
  • id names are defined with a "#", for example ("#tittle-1")
  • text are defined with "text=", for example ("text=Football Club")
  • You can use the playwright debugger to help you with the naming
PWDEBUG=1 npx playwright test

Because we need to wait for the site to be fully loaded before taking the screenshot we used the ".isVisible" and we target both Tawk elements

await page.isVisible('.tawk-text-truncate');
await page.isVisible('.tawk-icon-right');

Just in case, we add a time out of 1 second to avoid any type of connection error, or slow interface.

Since both of the sites https://herbivorehacker.subscriby.shop/ and https://footballclub.subscriby.shop/ loads fast and loads every element at the same time we just need to wait to read the title name and get the screenshot.

This will finalise the test successfully. If you want to know how to configure this repository just follow the instructions found at: karmacomputing/playwright-testing

Errors you might encounter:

Error: expect(received).toBe(expected) //Object. is equiality

Expected: "subscribie"

Received": "Subscribie"

This error is caused because of the line

expected(name).toBe('subscribie');

Is misspelled with a lower case "s". Playwright is case sensitive. So, its telling you that the value of the class ".navbar-brand" is Subscribie instead of subscribie.

Error: Snapshot comparison failed:

This can be because two reasons:

  1. The site css changed
  2. The comparisons from the first (expected) screenshot and the current test (Received) have some difference. Which can mean that the browser didn't fully load the site before the screenshot was taken.

You can see the difference, Expected (First screenshot), and the Received (last test run) in the /test-results/ folder so you can adjust the test to get that element in the website.