Blog by Railsware

How to Test Chrome Extensions with Playwright

It’s frustrating for users when an extension regularly crashes, freezes, or fails to function as expected. Negative reviews, product abandonment, and ultimately, revenue losses are all situations that developers want to avoid. Not to mention, the process of fixing unstable extensions can be time-consuming and costly. So, it’s vital to ensure that your extension remains stable and reliable after changes have been made. In this article, we’ll explain how to accomplish this via end-to-end testing.

To ensure your extension works properly, it’s essential to test it as closely as possible to how users will interact with it. To do this, we’ll write end-to-end tests using a tool called Playwright. Here are a few reasons why it’s the right tool for this task:

Getting set up

The first step in the process is to set up your testing environment. So, to add Playwright to your project run:

npm init playwright@latest

or see more installation options.

The installer will ask you:

After installation, you’ll see example specs and a Playwright config.

Since we’ll only be testing Chrome extensions here, we can remove Firefox and Webkit in Playwright config:

...
projects: [{
  name: "chromium",		
  use: {			
    ...devices["Desktop Chrome"],	
  },	
}],
...

Once you’ve set up Playwright, you’ll be able to launch example tests using the command npx playwright test.

Add extension to Playwright configuration

To test your extension, you’ll need to create a browser context with the extension enabled. This can be done using a helper function that launches a persistent context in Chrome. Here’s an example of what the code might look like:

import { chromium } from "@playwright/test";
import path from "path";

...

export const createBrowserContext = async () => {
  // assuming your extension is built to the 'public' directory	
  const pathToExtension = path.join(__dirname, './public')	
  const userDataDir = '/tmp/test-user-data-dir'	
  const browserContext = await chromium.launchPersistentContext(		
    userDataDir,	
    {	
      headless: false,	
      args: [`--disable-extensions-except=${pathToExtension}`],	
      ignoreDefaultArgs: ['--disable-component-extensions-with-background-pages'],	
    }
)}

Note: By default, Chrome’s headless architecture mode in Playwright does not support Chrome extensions. To overcome this limitation, you can use a workaround like this:

const browserContext = await chromium.launchPersistentContext(
  userDataDir,	
  {		
    headless: false,	
    args: [		
      `--disable-extensions-except=${pathToExtension}`,		
      '--headless=chromium'	
    ],	
    ignoreDefaultArgs: ['--disable-component-extensions-with-background-pages'],
  }
)

For more detail and alternatives around testing Chrome extensions, check out this guide in Playwright docs.

Writing tests

Now, it’s time to write the test. Here’s an example of what the finished product might look like:

import { test, expect } from '@playwright/test'

test.describe('Test some behaviour of page and extension', () => {	
  test('Look for Earth', async () => {		
    const browserContext = await createBrowserContext()	
    const page = await browserContext.newPage()	
    await page.goto('https://www.google.com/')
	
    const searchCombobox = await page.getByRole('combobox')	
    expect(searchCombobox).toBeVisible()	
    
    await searchCombobox.fill('planet earth wiki')	
    await page.keyboard.press('Enter');
    await page.getByRole('link', { name: /Earth - Wikipedia/ }).click()	
    await page.waitForURL('https://en.wikipedia.org/wiki/Earth')
	
    expect(page.getByText('Earth')).toBeVisible()
		
    browserContext.close()
  })
})

The above code snippet demonstrates a very basic example. So you will probably need to make adjustments (describing the behavior specific to your extension and what it does with web pages). Once you’ve formulated the test, you can run it using the command npx playwright test path/to/file.

If you need to debug your tests, you can use the --debug flag to walk through the test one step at a time.

npx playwright test path/to/file --debug

Running tests in debug mode has its benefits since you can:

Here’s what that might look like:

https://railsware.com/blog/wp-content/uploads/2023/02/Untitled-1.mp4

Add Playwright to GitHub CI

If you generated a GitHub workflow during Playwright installation, you can just push it as is and CI will launch Playwright tests. The only caveat is that if you run tests in headful mode, you should do so with XServer running. To do that, change the line launching tests to this:

xvfb-run npx playwright test

Pro tips

https://railsware.com/blog/wp-content/uploads/2023/02/Untitled-2.mp4

Wrapping up

End-to-end testing is the best way to prevent bugs and instabilities from showing up in your extensions. Taking a methodical approach to writing and debugging tests will help you minimize mistakes and improve the reliability of your solution. Meanwhile, robust tools like Playwright take the hassle out of test automation and test environment setup. With the above knowledge, you can be confident that your extensions will continue to provide a smooth user experience even after changes are made.

Exit mobile version