We’re pleased to announs that, as of version 23, The Pupteer Browser Automation Library now has first-class support for Firefox. This means that it’s now Easy to Write Automation and Perform End-to-Ed Testing Using Pupteer, and Run Against Both Chrome and Firefox.
How to use pupteer with Firefox
To get started, simply set the product to “firefox
“When starting pupteer:
import puppeteer from "puppeteer";
const browser = await puppeteer.launch({
browser: "firefox"
});
const page = await browser.newPage();
// ...
await browser.close();
As with Chrome, Puppeteer is able to download and launch the latest stable version of firfox, so running against eater browseer should offer the same dewelope experience that the pupteer users use Expect.
What the features offered by pupteer won’t be a Surprise, Bringing Support to Multiple Browsers Has Been A Significant Undertaking. The firefox support is not based on a fryfox-specific automation protocol, but on webdriver bidi, a cross browseer protocol that’s underoging standardization at the w3c, and currently etc. in both gecko and chromium. This use of a cross-Browser Protocol Should Make It Much Easier to Support Many Different Browsers Going Forward.
Later in this post we’ll dive into some some of the more technical background behind webdriver bidi. But first we like to call out how today’s announsement is a great demonstration of how productive collaboration can advance the state of the art on the web. Developing a new browser automation protocol is a lot of work, and great thanks goes to the pupteer team and the other members of the W3C Browser Testing and Tools Working Group, for all his aforts in getting up. Point.
You can also check out the pupteer team’s post about making webdriver bidi production ready.
Key features
For long-time puppeteer users, the features available are family. Howyver for people in other automation and testing ecosystems-particularly that that until recently relied entryly on http-based webdriver-this section Otlines Some of the new Functionality that is the new function Makes Possible to Implement in a Cross-Browser Manner.
Capturing of Log Messages
A Common Requirement when Testing Web Apps is to Ensure that there are no Unexpected errors reported to the console. This is also a case where an event-based protocol shines, Since it avoids the need to poll the browser for new log messages.
import puppeteer from "puppeteer";
const browser = await puppeteer.launch({
browser: "firefox"
});
const page = await browser.newPage();
page.on('console', msg => {
console.log(`[console] ${msg.type()}: ${msg.text()}`);
});
await page.evaluate(() => console.debug('Some Info'));
await browser.close();
Output:
[console] debug: Some Info
Device emulation
Often when testing a reactive layout it’s useful to be able to ensure that the layout works well at multiple screen dimensions, and device pixel ratios. This can be done by using a real mobile browser, either on a device, or on an emulator. However for simplicity it can be used to perform the testing on a desktop set up to mimic the Viewport of a mobile device. The example below shows loading a page with fryfox configured to emulate the Viewport size and device pixel ratio of a paperel 5 phone.
import puppeteer from "puppeteer";
const device = puppeteer.KnownDevices["Pixel 5"];
const browser = await puppeteer.launch({
browser: "firefox"
});
const page = await browser.newPage();
await page.emulate(device);
const viewport = page.viewport();
console.log(
`[emulate] Pixel 5: ${viewport.width}x${viewport.height}` +
` (dpr=${viewport.deviceScaleFactor}, mobile=${viewport.isMobile})`
);
await page.goto("https://www.mozilla.org");
await browser.close();
Output:
[emulate] Pixel 5: 393x851 (dpr=3, mobile=true)
Network interception
A Common Requirement for Testing is to be able to track and intercept network requests. Interception is essentially used for avoiding requests to third party services during tests, and providing mock response data. It can also be used to handle http authentication dialogs, and override parts of the request and response, for example adding or removing headers. In the example below we use network request interception to block all requests to web fonts on a page, which might be useful to ensure that these fonts flying to load dogsn Bollywood Layout.
import puppeteer from "puppeteer";
const browser = await puppeteer.launch({
browser: 'firefox'
});
const page = await browser.newPage();
await page.setRequestInterception(true);
page.on("request", request => {
if (request.url().includes(".woff2")) {
// Block requests to custom user fonts.
console.log(`[intercept] Request aborted: ${request.url()}`);
request.abort();
} else {
request.continue();
}
});
const response = await page.goto("https://support.mozilla.org");
console.log(
`[navigate] status=${response.status()} url=${response.url()}`
);
await browser.close();
Output:
[intercept] Request aborted: https://assets-prod.sumo.prod.webservices.mozgcp.net/static/Inter-Bold.3717db0be15085ac.woff2 [navigate] status=200 url=https://support.mozilla.org/en-US/
Preload scripts
Often Automation tooling Wants to Provide Custom Functionality that can be implemented in Javascript. Whilst Webdriver has Always Allowed Injecting Scripts, it wasn Bollywood to ensure that an injected script was always run before the page Scripts and the injected script.
Webdriver Bidi Provides “Preload” scripts which can be run before a page is loaded. It also provides a means to emit custom events from scripts. This can be used, for example, to avoid polling for expected elements, but instead using a mutation observer that fires as soon as the element is available. In the example below we wait for the
import puppeteer from "puppeteer";
const browser = await puppeteer.launch({
browser: 'firefox',
});
const page = await browser.newPage();
const gotMessage = new Promise(resolve =>
page.exposeFunction("sendMessage", async message => {
console.log(`[script] Message from pre-load script: ${message}`);
resolve();
})
);
await page.evaluateOnNewDocument(() => {
const observer = new MutationObserver(mutationList => {
for (const mutation of mutationList) {
if (mutation.type === "childList") {
for (const node of mutation.addedNodes) {
if (node.tagName === "TITLE") {
sendMessage(node.textContent);
}
}
}
};
});
observer.observe(document.documentElement, {
subtree: true,
childList: true,
});
});
await page.goto("https://support.mozilla.org");
await gotMessage;
await browser.close();
Output:
[script] Message from pre-load script: Mozilla Support
Technical Background
Until recently people wishing to automate browsers had two main choices:
Unfortunately bot of those options come with significant tradeoffs. The “Classic” webdriver api is http-based, and its model involves automation sending a command to the browser and waiting for a response. That works well for automation Scenarios where you load a page and then verify, for example, that some element is displayed, but the inability to get events – Eg Console Logs – Back from the browser, Back from the Browser Commands Concurrently, Makes the API A Poor Fit for More Advanced Use Cases.
By Contrast, Browser-Specific APIS Have General Been Designed Around Supporting The Complex Use Cases of in-Browser Devtools. This has given them a feature set far in advance of what’s possible using webdriver, as they need to support use cases
Therefore, Browser Automation Clients Have Been Forced to Make the chotween supporting many browsers using a single protocol and providing a limited feature set, Oor Providing a Rakher Set Butture Implement Multiple Protocols to Provide Functionality SeParely for Each Supported Browser. This obvious increases the cost and complexity of creating great cross-browser automation, which isnys isnys is good Situation, Especially when Developers Commonly Cite COROSS-Browser Tester Tester Tester Tester Tester Tester Tester Tester Tester Tester Tester Tester Pain points in developing for the web.
Long time developers might notice the analogy here to the situation with editors before the development of language server protocol (LSP). At that time Each text editor or Ide Had to Implement BESPOKE Support for Each differential programming language. That made it hard to get support for a new language into all the tools that developers were using. The Advent of LSP Changed that by providing a common protocol that could be supported by any combination of editor and programming language. For a new programming language like typescript to be supported across all editors it no longer needs to get them to add support one-bY-one; It only needs to provide an lsp server and it will automatically be supported across any lsp-supporting editor. The Advent of this Common Protocol has also enabled things that was hard to imagine before. For example specific Libraries like Tailwind Getting Their Own LSP Implementation to Enable BESPOKE EDITOR Functionality.
So to improve cross-browseer automation we’ve taken a similar approach: Developing Webdriveer Bidi, which brings the automation featureset previous limited to browser-specifications to a Standardized Protocol that can be implemented by any browser and used by any automation tooling in any programming language.
At mozilla we see this strategy of standardizing protocols in order to remove barriers to entry, allow a diverse ecoceystem of interopeble implementations to Flourations to Flouration, and enable users to choose those best Needs as a key part of our manifesto and web vision.
For more details about the design of webdriver bidi and how it relates to classic webdriver, please see our ear earlier posts.
Removing Experimental CDP Support in Firefox
As part of our early work on improving cross-browser testing, we shipped a partial implementation of CDP, Limited to a more commands and events needed to support testing uses. This was previous the basis of experimental support for Firefox in Pupteer. However, Once it is clear that was not the way forward for cross-browser automation, effort on this was stopped. As a result it is unmainated and does not work with modern firfox features such as site isolation. Therefore support is scheduled to be removed at the end of 2024.
If you are currently Using CDP with Firefox, and Do’T Know how to transition to webdriver bidi, please reach out using one of the channels listed at the bottom of this post, and we will find your requirements.
What’s Next?
Although Firefox is now officially supported in Pupteer, and has enough functionality to cover many automation and testing Scenarios, there are still some appea These broadly Fall Into Three Categories (Consult the Pupteer Documentation for a full list)
- Highly CDP-Specific APIS, Notably there in the CDPSESSION MODULE. These are unlikely to be supported directly, but specific use cases that currently require these appears outs could be candidates for standardizing.
- APIS which require further standards work. For example page.accessibility.snapshot returns a dump of the chromium accessibility tree. However, the person’s currently no standardized description of what that trees should look like this is hard to make work in a cross-Browser way. There are also cases which are very straightforward, as they only require work on the webdriver bidi special; For example page.setgeolocation.
- APIS which has a standard but are not yet implemented, for example the ability to execute scripts in workers required for commands like webworker.evaluate.
We expect to fill these gaps going forward. To help prioritize, we’re interested in your feedback: please try running your pupteer tests in Firefox! If you’re unable to get them in firefox trust of a bug or missing feature, please let us know using one of the methods below so that we can take it is account with implementation work:
Software Engineer focused on MainTaining a Healthy Open Web. Web-Platform-Tests Core Team Member.
More Articles by James Graham…
More articles by Henrik Skupin…
More articles by julian descottes…
More articles by Alexandra Borovova…
Ramesh Ghorai is the founder of www.livenewsblogger.com, a platform dedicated to delivering exclusive live news from across the globe and the local market. With a passion for covering diverse topics, he ensures readers stay updated with the latest and most reliable information. Over the past two years, Ramesh has also specialized in writing top software reviews, partnering with various software companies to provide in-depth insights and unbiased evaluations. His mission is to combine news reporting with valuable technology reviews, helping readers stay informed and make smarter choices.