The original
The transition from Puppeteer to ourselves may be easy, but is it worth it? What are the specific changes at the coding level? What are the new features and functions? This is our main concern in this article
The state of Puppeteer and offender
The two tools have a lot in common, but the two have grown at different paces in the past two years, leapfrog the Puppeteer. This trend has led many to move down the drain, and this article will describe the steps and the new features the change may bring. Although this article is a bit longer, it is easy to grasp.
Why migrate
In our previous tests, we have linked to Cypress, Selenium, Puppeteer and ourselves for the following reasons:
Playwright
Updates are more active and are less in terms of new featuresPuppeteer
More obviousPlaywright
Performance benefits in real-world end-to-end (E2E) testing (see details)The article links), test case execution is fasterPlaywright
Better stabilityPlaywright
inGitHub.Twitter.SlackWait for the neighborhood to get even hotterPuppeteer
The neighborhood is a little quieter
Change list
Here’s a comparison chart, read it for a few minutes, and we’ll talk more about it later
Puppeteer | Playwright |
---|---|
puppeteer.launch(...) |
playwright.chromium.launch(...) |
browser.createIncognitoBrowserContext(...) |
browser.newContext(...) |
page.setViewport(...) |
page.setViewportSize(...) |
page.waitForSelector(selector) page.click(selector); |
page.click(selector) |
page.waitForXPath(XPathSelector) |
page.waitForSelector(XPathSelector) |
page.$x(xpath_selector) |
page.$(xpath_selector) |
page.waitForNetworkIdle(...) |
page.waitForLoadState({ state: 'networkidle' }}) |
page.waitForFileChooser(...) |
Removed, handled differently. |
page.waitFor(timeout) |
page.waitForTimeout(timeout) |
page.type(selector, text) |
page.fill(selector, text) |
page.cookies([...urls]) |
browserContext.cookies([urls]) |
page.deleteCookie(... cookies) |
browserContext.clearCookies() |
page.setCookie(... cookies) |
browserContext.addCookies(cookies) |
page.on('request', ...) |
Handled through page.route. |
elementHandle.uploadFile(...) |
elementHandle.setInputFiles(...) |
Tricky file download. | Better support for downloads. |
Change the details
Package introduced
In Puppeteer, the first few lines of a script might look something like this:
const puppeteer = require('puppeteer');
(async() = > {const browser = await puppeteer.launch();
const page = await browser.newPage();
// ...
Copy the code
Down the drain, it goes like this:
const { chromium } = require('playwright');
(async() = > {const browser = await chromium.launch();
const page = await browser.newPage();
// ...
Copy the code
Down the drain, the offender provides out-of-the-box cross-browser support, allowing you to choose which browser you want to run, such as const {webkit} = require(‘ ourselves ‘); , Puppeteer needs to be configured through the launch interface:
const browser = await puppeteer.launch({ product: 'firefox' })
Copy the code
The context browser
A browser context exists in Puppeteer:
const browser = await puppeteer.launch();
const context = await browser.createIncognitoBrowserContext();
const page = await context.newPage();
Copy the code
In ourselves, the context is more important and is used slightly differently:
const browser = await chromium.launch();
const context = await browser.newContext();
const page = await context.newPage();
Copy the code
As with Puppeteer, the default context can be used for basic use and single-page streams:
const browser = await chromium.launch();
const page = await browser.newPage();
Copy the code
wait
The offender’s auto-waiting mechanism means you may not have to wait explicitly as often. However, waiting is one of the trickiest parts of UI automation, and you still need to know the different ways to have scripts explicitly wait for one or more conditions to be satisfied. In this regard, the offender has brought a few changes you might want to watch out for:
- Page.waitfornavigation and Page.waitForSelector remain, but are not required in many use cases with automatic waiting
- A new page. WaitForEvent
Puppeteer
thepage.waitForXPathIt’s integratedpage.waitForSelectorSupports automatic identificationXPath
expression- Remove page.waitForFileChooser. See Upload Files, E2E Account Settings for new usage
- Page.waitfornetworkidle is integrated into Page.waitForLoadState
- Added page.waitForURL to allow waiting for a URL to complete loading by the page’s main frame
- Page.waitfor (timeout) becomes Page.waitforTimeout (timeout)
Note that Page.waitForTimeout should not be used in the official production release, and the hard wait is only used for testing
Set the viewport
The page. SetViewport of the Puppeteer becomes page. SetViewportSize in the offender
Typing
Puppeteer’s Page. Type is still available, controlling fine-grained keyboard events, and the offender has added Page. Fill, used to fill and empty forms
Cookies
Cookies are processed at the page level with Puppeteer; With the offender, you can manipulate them at the BrowserContext level
Before:
page.cookies([...urls])
page.deleteCookie(... cookies)
page.setCookie(... cookies)
Now:
browserContext.cookies([urls])
browserContext.clearCookies()
browserContext.addCookies(cookies)
Notice the subtle differences between these methods, and how cookies are passed to them
XPath selectors
With / / or.. The initial XPath selector will be automatically identified, while the Puppeteer has a separate interface
The device emulation
The offender’s device emulation is provided at the browser context level:
const pixel2 = devices['Pixel 2']; const context = await browser.newContext({ ... pixel2, });Copy the code
In addition, you can control permissions, geographic location, and other device parameters.
File download
Trying to download files in headless Puppeteer mode can be tricky, and the offender may be leaner:
const [download] = await Promise.all([
page.waitForEvent('download'),
page.click('#orders > ul > li:nth-child(1) > a')])const path = await download.path();
Copy the code
This is a complete example
File upload
The Puppeteer elementHandle. The uploadFile becomes elementHandle setInputFiles
For details, see file upload examples.
Request to intercept
Request interception in Puppeteer is via page.on(‘request’,…) Implementation:
await page.setRequestInterception(true)
page.on('request', (request) => {
if (request.resourceType() === 'image') request.abort()
else request.continue()
})
Copy the code
In the ourselves, the page. Route may block the url of the specified pattern:
await page.route('* * / *'.(route) = > {
return route.request().resourceType() === 'image'
? route.abort()
: route.continue()
})
Copy the code
See the full example
Notable new features
Be sure to be aware of the many new features of ourselves when moving from Puppeteer to ourselves, as they may offer new solutions and possibilities for testing or monitoring setups
New selector engine
The offender provides a more flexible way to reference UI elements, adding the following methods in addition to CSS and XPath:
Playwright
Specific selectors, for example:nth-match(:text("Buy"), 3)
- Text selectors, for example
text=Add to Car
- Chain selectors, for example
css=preview >> text=In stock
In addition, you can create your own custom selector engine
For more information about and usage of selectors, see Working with Selectors
Save and reuse state
The offender can easily save the authentication state (cookie and localStorage) for a given session and use it later when the script runs to save authentication time
Locate the API
The Ourselves Locator API encapsulates the logic needed to retrieve a given element, allowing users to easily get the latest DOM element in a script at different points in time
Inspector
The Offender Inspector is a GUI tool that comes in handy when debugging scripts. It allows the consumer to step through the instructions in the script, making it easier to determine the cause of the failure.
Test
The offender has a Test mechanism that can be useful in E2E testing, such as out-of-the-box parallelization, hooks, and so on
Track view
Offender’s Trace Viewer allows you to explore traces recorded using the Playwriter Test or BrowserContext tracing API. Tracing provides the most detailed insight into script execution
Test generator
You can use the ourselves Test Generator to record the interaction in the browser. The output will be a complete script that can be checked and executed