There are many ways to test a program. Start with small unit tests and move on to larger user interface tests. Puppeteer is definitely in the latter category.

Puppeteer advertises itself as

In short, Puppeteer makes user interface testing easy, based on the Chrome Devtools protocol. And all of this is free.

What is Puppeteer?

Puppeteer is a user interface automation tool. It does this by using a combination of Chrome interface free mode and the DevTools protocol. As mentioned in the above reference, it uses a higher-level API to encapsulate its functionality, making user interface test automation a breeze.

A number of Google Chrome tools have been developed based on the Chrome DevTools protocol. You go to more Tools -> Developer Tools in your browser and DevTools opens up. The DevTools protocol is the driving force behind DevTools, and we can now do a lot more with DevTools in Chrome.

Chrome without an interface is Chrome without Chrome. Yes, you read that right. It allows you to interact with Chromium from outside the browser, on the command line.

Bringing Chromium and Blink rendering engines into the command line makes it possible to do a lot of things like automated testing.

The installation

Installation is simple and can be done through YARN or NPM. Simply run the following command:

__Tue Sep 26 2017 14:37:37 GMT+0800 (CST)____Tue Sep 26 2017 14:37:37 GMT+0800 (CST)__yarn add pupeeter
# or "npm i puppeteer"
__Tue Sep 26 2017 14:37:37 GMT+0800 (CST)____Tue Sep 26 2017 14:37:37 GMT+0800 (CST)__Copy the code

You can then run node just like any other NodeJS program.

Create a screenshot

Sometimes you want to test things like CSS to make sure the look and feel of your site isn’t falling back.

For example, take a screenshot of my blog’s front page:

__Tue Sep 26 2017 14:37:37 GMT+0800 (CST)____Tue Sep 26 2017 14:37:37 GMT+0800 (CST)__const puppeteer = require("puppeteer"); (async() => { const browser = await puppeteer.launch(); const page = await browser.newPage(); await page.goto("http://jackhiston.com/"); await page.screenshot({ path: "jackhiston-blog.png" }); browser.close(); }) (); __Tue Sep 26 2017 14:37:37 GMT+0800 (CST)____Tue Sep 26 2017 14:37:37 GMT+0800 (CST)__Copy the code

First we reference puppeteer as a dependency package. With this, you can launch a browser instance, which can actually also load the browser on the screen, as follows:

__Tue Sep 26 2017 14:37:37 GMT+0800 (CST)____Tue Sep 26 2017 14:37:37 GMT+0800 (CST)__const browser = await puppeteer.launch({ headless: false }); __Tue Sep 26 2017 14:37:37 GMT+0800 (CST)____Tue Sep 26 2017 14:37:37 GMT+0800 (CST)__Copy the code

Note the headless option.

This allows you to create a new page as you browse, and then you can “go” to a specific url (in this case, to my home page).

We can then save screenshots of the page using the built-in screenshots feature.

Crawl web pages

Another application scenario is to use Puppeteer to crawl the contents of a web site. In the following example, I’ll browse hacker news and get links to all the news from the first page:

__Tue Sep 26 2017 14:37:37 GMT+0800 (CST)____Tue Sep 26 2017 14:37:37 GMT+0800 (CST)__const puppeteer = require("puppeteer"); (async() => { const browser = await puppeteer.launch(); const page = await browser.newPage(); page.on("console", (... args) => console.log("PAGE LOG:", ... args)); await page.goto("https://news.ycombinator.com", { waitUntil: "networkidle" }); const links = await page.evaluate(() => { const anchors = Array.from(document.querySelectorAll(".storylink")); return anchors.map(anchor => anchor.textContent); }); console.log(links.join("\n")); browser.close(); }) (); __Tue Sep 26 2017 14:37:37 GMT+0800 (CST)____Tue Sep 26 2017 14:37:37 GMT+0800 (CST)__Copy the code

The one thing to note here is the Page. Evaluate function. It allows us to examine the current page, just as we do in DevTools for Chrome.

Click on the link and browse

The last use case I want to show you is navigation. In the example below, I show how you can click on a page link and wait for the page to load, recording the results:

__Tue Sep 26 2017 14:37:37 GMT+0800 (CST)____Tue Sep 26 2017 14:37:37 GMT+0800 (CST)__const puppeteer = require("puppeteer"); (async() => { const browser = await puppeteer.launch(); const page = await browser.newPage(); await page.goto("https://news.ycombinator.com", { waitUntil: "networkidle" }); await page.click("a.storylink"); var response = await page.waitForNavigation({ waitUntil: "networkidle" }); console.log(await page.title()); console.log(page.url()); browser.close(); }) (); __Tue Sep 26 2017 14:37:37 GMT+0800 (CST)____Tue Sep 26 2017 14:37:37 GMT+0800 (CST)__Copy the code

Here, page. WaitForNavigation is a key feature. We can wait until the page loads because the promise only ends when the click event is complete.

This is useful for browsing navigation, and allows for full UI user experience testing.

conclusion

Puppeteer focuses on providing apis to demonstrate the capabilities of the DevTools protocol.

Tools like Selenium are more sophisticated and offer cross-browser testing. Puppeteer does not fall into the category of Selenium.

Puppeteer is just one of many applications for Chrome that have no interface. At the time of this writing, there are a number of projects using interface less Chrome. Ken Soh’s blog is a good introduction to this. Other projects using the DevTools protocol can be found here.

Puppeteer is maintained by the Chrome DevTools team, who are looking for talented people to contribute to the community. So, you can drive interface free Chrome automated testing by joining the Puppeteer open source project.

Thanks for reading. Please share with your friends.

Useful links

  • Puppeteer example
  • Chromeless, Chrominator, Chromy, Navalia, Lambdium, GhostJS, AutoGCD
  • DevTools agreement
  • Chrome DevTools
  • The interface of Chrome

Making a Master Puppeteer


Thanks to Xue Mingdeng for correcting this article.

To contribute or translate InfoQ Chinese, please email [email protected]. You are also welcome to follow us on Sina Weibo (@InfoQ, @Ding Xiaoyun) and wechat (wechat id: InfoQChina).