Blog

Automated cross-browser testing with Playwright

05 Jun, 2020
Xebia Background Header Wave

Introduction

Automated browser testing is essential for asserting the quality of the code you deliver when developing web applications. Some defects only become visible at the point when you tie everything together in your application. You want to catch these defects as early as possible to minimize the cost of fixing them. There are a lot of great tools out there to help you with this and I would like to highlight a tool named Playwright.

Microsoft released Playwright on 31 January 2020 and has an active community that keeps adding features. In this blog post, I will explain what Playwright is and how it can help you to improve the quality of your web application when you target various devices.
Playwright is a Node library that enables cross-browser web automation. You can also hook up existing test runners and target emulated devices.

You can find the complete repository on Github.

Prerequisites

In the next sections, I will explain how you can set up Playwright for an existing Angular application. Nevertheless, you can apply this to any front-end framework/library. In fact, there is zero Angular code in this blog post.

The basic requirements are:

  1. You have a web application that you can run locally in your browser window.
  2. You are using one of the supported test runners (Jest, Jasmine, AVA, or Mocha)

A default Angular project

When you create an angular project with the CLI, it creates an e2e folder with a protractor configuration by default. We will reuse this configuration to add Playwright.

Project e2e folder structure

Installation

Let’s start by installing playwright:

npm i --save-dev playwright

Now we create a new spec file, say “app-playwright.e2e-spec.ts”:

Playwright spec file

In the protractor.conf.js file we change specs to only include the Playwright file:

exports.config = { allScriptsTimeout: 11000, specs: [ './src/**/*playwright.e2e-spec.ts' ],

Next, let’s run Chrome in headless mode since Playwright runs its own instance of Chrome:

Your first test

We can write a first test in the app-playwright.e2e-spec.ts as follows:

import { chromium, Browser, Page } from 'playwright';

describe('Angular app homepage', () => {
  let browser: Browser;
  let page: Page;

  beforeAll(async () => {
    browser = await chromium.launch({ headless: false });
    page = await browser.newPage();
  });

  it('Should display the correct page title', async () => {
    await page.goto('https://localhost:4200');
    expect(await page.title()).toBe('MyAngular9AppPlaywright');
  });

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

The browser platform can be specified by importing chromium, Firefox, and/or Webkit. With the launch command, the browser will launch by default in headless mode.


We need a page object to start navigation and load the DOM. In the first test, Jasmine checks and asserts the page title.
A second example to check a DOM element can be specified as follows:

it('should display welcome message', async () => {
    await page.goto('https://localhost:4200');
    const titleBannerContents = await page.$eval(
      'app-root .content span',
      (el: HTMLElement) => el.innerText
    );
    expect(titleBannerContents).toBe(
      'my-angular9-app-playwright app is running!'
    );
  });

With the $eval function you can use a query selector syntax. Here it will search for the first occurrence of the <app-root> element, a descendant with the “content” class and finally a descendant with a <span> element. This corresponds to the following visual representation of the element:

HTML component to check

We use the span element’s inner text to match it to the expected value. After the tests finish we clean up the browser object.
We run the test with the command “ng e2e” and the result will be the following:

Result of ng e2e command

The tests run too fast for the eye to follow. You can slow this down by the slowMo option:

Device emulation

With Playwright you can easily emulate a large variety of devices. Suppose you want to check how responsive your web application is. You can do this by targeting different viewport sizes. In Playwright you can specify this by the name of the device. You can find the full list of supported devices on https://github.com/Microsoft/playwright/blob/master/src/deviceDescriptors.ts.

 

A default Angular application is responsive, but as your application grows and becomes more complex, so does your UI. Suppose we would have the following HTML in the app.component.html file:

<!-- Strangely styled link -->
  <div style="width: 400px; margin-top: 16px">
    <a href="https://www.google.com" id="unclickable_link">OK</a>
  </div>

And add the following test:

it('should display the full link on mobile', async () => {
    await page.goto('https://localhost:4200');
    const checked = await page.click('#unclickable_link');
    console.log(checked);
});

On a desktop resolution, you can see the OK link clearly:

Link is visible on desktop resolution

On the Galaxy S5 for example, you cannot see the link, because it is outside the viewport boundaries:

Link not visible on Galaxy S5 resolution

To write a test for the Galaxy S5, we need to change the “beforeAll” function code to the following:

beforeAll(async () => {
    browser = await chromium.launch({ headless: false });
    //With Galaxy S5 The third test will fail
    const galaxyS5 = devices['Galaxy S5'];
    const context = await browser.newContext({
      ...galaxyS5,
    });
    page = await context.newPage();
  });

When we run “ng e2e”, the test will fail:

Test fails on Galaxy S5 resolution

If found, people often find these kinds of failures late in the process. For example, when testers do exploratory testing on physical devices or even later when end-users use the application on the production environment.

Conclusion

Playwright is a powerful tool to write tests and assert the quality of your web application. Although the people behind Playwright formulate it as a library that enables cross-browser web automation, you can also use it to write UI, end-to-end, and component tests. In this way, you can write tests that catch defects early in the development process and that will decrease the cost to fix them.

For me, the features that stand out are:

  1. The ease of setting Playwright up.
  2. Ease of creating cross-browser and cross-device testing.
  3. Performance of cross-browser and cross-device tests. I have copied my first three tests 14 times to see that it took less than 7 seconds to run 42 tests. A more extensive performance set up would be required to study this further, but I find this outcome very promising.

In this blog post, I only scratched the surface of the many things you can do with Playwright. Check out https://playwright.dev for more.

Your opinion

Thank you so much for reading my blog post. If you believe something is unclear or incorrect, please let me know. I am always open to feedback and eager to improve by learning from you.



I am a specialist at Qxperts. We empower companies to deliver reliable & high-quality software. Any questions? We are here to help! www.qxperts.io

Questions?

Get in touch with us to learn more about the subject and related solutions

Explore related posts