End-to-end testing for Chrome Extensions

End-to-end testing involves an extension package being built and loaded into a browser. A testing tool communicates with the browser to automate interactions and test the same flows that a user would go through. A library that supports end-to-end testing will generally provide ways of controlling the browser, simulating user input and observing the current state of any open pages.

See Testing Chrome Extensions with Puppeteer for a tutorial and Unit testing for details on writing unit tests for Chrome extensions.

Using browser testing libraries

Extensions are supported by a range of testing libraries.

Library Guidance
Puppeteer / Playwright See Chrome Extensions (Puppeteer / Playwright).
Selenium Use the ChromeOptions object to load extensions. More information is available here.
WebDriverIO See Web Extension Testing.

Running tests in headless Chrome

When running tests as part of an automated workflow, it is often necessary to load your extension on a machine that does not have a screen. Chrome's new headless mode allows Chrome to be run in an unattended environment like this. Start Chrome using the --headless=new flag (headless currently defaults to "old", which does not support loading extensions). Depending on the automation tool you choose, there may be a setting that adds the flag for you automatically.

Setting an extension ID

It is often desirable to have a fixed extension ID in tests. This makes many common tasks easier such as allow-listing the extension's origin on a server it needs to communicate with, or opening extension pages within tests. To do this, follow the steps under Keeping a consistent extension ID.

Testing extension pages

Extension pages can be accessed using their corresponding URL, e.g chrome-extension://<id>/index.html. Use the normal navigation methods available in your automation tool of choice to navigate to these URLs.

Testing an extension popup

Opening an extension popup in the context of another page is not currently possible. Instead, open the popup's URL in a new tab. If your popup uses the active tab, consider implementing an override where a tab ID can be passed explicitly to your popup. For example:

constURL_PARAMS=newURLSearchParams(window.location.search);
asyncfunctiongetActiveTab(){
// Open popup.html?tab=5 to use tab ID 5, etc.
if(URL_PARAMS.has("tab")){
returnawaitchrome.tabs.get(parseInt(URL_PARAMS.get("tab")));
}
consttabs=awaitchrome.tabs.query({
active:true,
currentWindow:true
});
returntabs[0];
}

Inspecting extension state

To avoid test failures when you change the internal behavior of your extension, it is generally best practice to avoid accessing internal state in an integration test. Instead, you should base your tests on what is visible to the user. However, it can sometimes be desirable to directly access data from the extension. In these cases, consider executing code in the context of an extension page.

In Puppeteer:

constworkerTarget=awaitbrowser.waitForTarget(
target=>target.type()==='service_worker'
);
constworker=awaitworkerTarget.worker();
constvalue=awaitworker.evaluate(()=>{
chrome.storage.local.get('foo');
});

In Selenium:

// Selenium doesn't allow us to access the service worker, so we need to open an extension page where we can execute the code
awaitdriver.get('chrome-extension://<id>/popup.html');
awaitdriver.executeAsyncScript(
'const callback = arguments[arguments.length - 1];'+
'chrome.storage.local.get(\'foo\').then(callback);'
);

Testing service worker termination

To learn about testing service worker termination, see testing service worker termination with Puppeteer. We also have a sample for Puppeteer and Selenium.

Note that when using some testing frameworks, service workers may not terminate automatically as they would in normal usage. This is the case in Selenium. It relies on ChromeDriver which attaches a debugger to all service workers preventing them from being stopped.

Except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 4.0 License, and code samples are licensed under the Apache 2.0 License. For details, see the Google Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.

Last updated 2023年10月12日 UTC.