By Martin Rifon

In Software Engineering, deploying to production is always a risk, but at the same time, it is always necessary. How else would you ship new features or bug fixes? Bugs are frequently introduced while deploying new features or fixing other bugs. We are only human, after all.

Given this scenario, it seems wise to invest time learning mechanisms that allow you to minimize the risk of introducing new bugs during deployment. In this blog post, we will take a look at one such tool, called Puppeteer, and how we can use it to implement end-to-end testing, in order to catch bugs before sending them to production. Along with Puppeteer we also use Jest, to facilitate testing.

End-to-end testing and Puppeteer

To start with, it might be a good idea to discuss what exactly is end-to-end testing? It actually is nothing more than a particular type of testing, where a flow from the system is evaluated and checked from start to finish. For example, in an e-commerce platform, an end-to-end test could be “Add item to cart”. The process starts with the user picking an item in the online store, selecting the option to add to cart, opening the cart details, and finally checking that the item was added to the cart.

And what is Puppeteer? It is a Node library made by the Chrome DevTools team, offering a high level API used to control either Chrome or Chromium. It can do a fair amount of things, but here we’ll focus on how it helps end-to-end testing.

To set up Puppeteer, you can either create an entirely new project or use your existing application. Once that’s done, all that remains is to write the actual tests and fire them away.

 

Puppeteer           "Jest

Setting up a project with Jest and Puppeteer

Aside from installing Jest and Puppeteer, you should also add the preset jest-puppeteer to your jest config file.

We’ll be using Mapright in this example, one of our amazing clients. The Puppeteer test here describes a simple login function:

// Let's increase the timeout in order to be safe.

jest.setTimeout(120000);

describe('Login', () => {

 beforeEach(async () => {

   await page.goto('https://mapright.com/users/sign_in');

 });

 it('should fail login', async () => {

   // Remember you can take screenshots in order to debug issues.

   // For instance:

   // await page.screenshot({ path: 'step_1.png' });

   await page.type("input[name='email']", 'john.doe@example.com');

   await page.type("input[name='password']", 'password');

   await page.click("button[type='submit']");

   await page.waitForSelector('.sign-in-form__error');

   const signInError = await page.evaluate(() => (

     document.querySelector('.sign-in-form__error').innerText

   ));

   expect(signInError).toContain('Invalid email or password');

 });

 it('should login successfully', async () => {

   await page.type("input[name='email']", '[VALID_EMAIL]');

   await page.type("input[name='password']", '[VALID_PASSWORD]');

   await page.click("button[type='submit']");

   // Wait for the request to be completed.

   await page.waitForNavigation({ waitUntil: 'networkidle0' });

   // Check that login was a success.

   expect(page.url()).toContain('dashboard');

 });

});

Mitigating risk of missing bugs

There’s one major caveat in this approach; Puppeteer only handles Chrome. So, by running your end-to-end tests only with Puppeteer, you run the risk of missing bugs that only happen in other browsers, such as Firefox or Edge. This risk can be mitigated by ensuring good cross-browser compatibility, or by using a tool such as Selenium that offers an API supporting all major browsers. Selenium is a great tool but as it is built to support all modern browsers it is prone to performance implications.

Your road to Puppet Master

We’ve only scratched the surface of what can be done with Puppeteer and how it can be integrated with a development workflow. Here are some ideas for your road to becoming the Puppet(eer) Master:

  • Use Puppeteer to generate PDF reports (yes, Puppeteer can create PDFs from the content of the browser).
  • Place it into a continuous integration workflow.
  • Follow the official Jest guide for integration with Puppeteer.
  • Crawl a single page application and use it to generate server side content.
  • Help diagnose performance issues.

And many more!

In this post, we learned what Puppeteer is and what it can be used for, how to use it in a real world application, and how to make further use of it. I hope you find this testing tool as useful as we have.

We at Moove It keep seeking new ways to help our agile software development and day-to-day activities. New technologies emerge frequently and staying on top of trends is key for us. Stay tuned for more of our informative software blog posts!