There are many ways to test a program. From starting miniscule with unit testing, to more grandiose UI testing. Puppeteer falls firmly in the latter category.

Puppeteer advertises itself as

a Node library which provides a high-level API to control headless Chrome over the DevTools Protocol

That is a lot of words. Puppeteer is a walking advertisement of the true potential the Chrome DevTools Protocol has to offer. It oozes ease at the seems, and will leave you with a sense of UI testing in it’s prime. All this and free!

What is Puppeteer?

Puppeteer is a UI automation tool. It achieves this by using the combination of headless chrome and the DevTools protocol. As the quote originally says, it is a higher level API that wraps this functionality, making certain UI test automations a breeze.

The Chrome DevTools Protocol exposes a set of tools that are built into the famous google chrome. DevTools is essentially you hitting More Tools -> Developer Tools within your browser. Therefore, the DevTools Protocol is the wheels to your DevTools-i.e., you can now get programmatical with the DevTools in Chrome.

Headless chrome is chrome without the chrome. Yes, you read that correctly. It allows you to interact with Chromium from an environment other than a browser-i.e., the command line.

Bringing the power of Chromium and the Blink rendering engine to your command line opens many doors. The biggest use case, is automated testing.

Installation

Installation is easy, as it can be done with yarn or npm. Just run the following command:

yarn add pupeeter # or "npm i puppeteer"

This can then be required and ran by node like any nodejs application.

Creating screenshots

There are times when you want to test things such as CSS. Making sure that your website’s look and feel has not regressed is important to check.

For example, to take a screenshot of the front page of my blog:

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(); })();

The first thing to do here is to include the puppeteer dependency. With this you can launch a browser instance, and this could actually load a browser on screen as well like so:

const browser = await puppeteer.launch({ headless: false });

Note the headless option.

With this you then create a brand new page like you would when navigating in a browser, and then you “goto” a specific url (in this case my home page).

We then can use a built-in screenshot functionality to save an image of my home page.

Crawling a website

Another use case for Puppeteer is crawling a websites content. In the next example I’m navigating to hacker news and scraping all the links off the first page:

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("

")); browser.close(); })();

One thing to note here is the page.evaluate function. This allows us to inspect the current page that we are on, as if we were in the DevTools area of chrome itself.

The final use case I want to showcase is navigation. In the following example I show how you can click a link on a page and wait for the page to finish loading, so as to record results:

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(); })();

an important function here is page.waitForNavigation. This allows us to wait until the click event has fully loaded the new web page, as the click event promise will finish when only the click event has.

This can be very useful for when navigating around, and testing a UI’s user experience is intact.

Summary

The main focus of Puppeteer is to provide an API that can show off the capabilities of the DevTools protocol.

Tools like Selenium are much more established, and offer cross browser testing as well. Puppeteer doesn’t belong in the same grouping as Selenium.

Puppeteer is just one example of many tools coming out around the headless chrome idiom. At the time of writing, there are now a lot of projects out there that use headless chrome. A good blog post that mentions some is here, by Ken Soh. Other places to look for existing projects using the DevTools protocol is here.

Puppeteer is maintained by the Chrome DevTools team, and they are looking for contributions! So head on over and be a part of this new movement of headless chrome automation testing.

Thanks for reading. Please share with friends.