End to end testing in React with Puppeteer and Jest

Benjamin Ajewole
4 min readMar 8, 2020

--

In my previous article, I wrote an introduction to web scraping using Puppeteer. Click here to view the post.

In this article, I’ll be writing about performing end to end testing in React with Puppeteer and Jest.

There are different type of software testing, they include, unit testing, integration testing, beta testing, smoke testing, alpha testing, end to end testing(e2e) etc.

End-to-end or e2e testing is a type of software testing that is used to test the flow of the Application to make sure it behaves as expected. The whole essence of end-to-end testing is to test from the end user’s experience. End-to-end testing helps to detect bugs easily, it also tests the correctness of the App and it also increases the test coverage of your App.

To get started, clone this GitHub repo. It contains a React boilerplate with two components

git clone https://github.com/Rexben001/react_puppeteer.git && cd react_puppeteer && npm install && npm start

If the commands were successful, it should launch a page like this

If you enter any correct email address and a password that has a length of at least six characters, it’ll take you to the next screen.

For example
Email: example@me.com
Password: 123456

But if you enter an invalid email or password, you’ll get an error notification

We are going to be writing end-to-end tests with Puppeteer and Jest.

Create a App.test.js inside the src folder.

You don’t need to install Puppeteer because when you ran the commands above it automatically installed Puppeteer.

If you don’t know how Puppeteer works, you can check my previous post on Puppeteer. https://medium.com/@rexben/introduction-to-web-scraping-with-puppeteer-1465b89fcf0b

Import Puppeteer

import puppeteer from 'puppeteer';

Create browser and page variables so that we can access from anywhere in the file.

let browser, page;

Add a beforeAll hook to create the browser and page that’d be used to run the test. This configuration will open a Chromium browser when you run a test and it’ll also slow down the operation of Puppeteer by 30 milliseconds so that we can see the interaction.

beforeAll(async () => {browser = await puppeteer.launch({headless: false,slowMo: 30});page = await browser.newPage();await page.goto('http://localhost:3000/');await page.waitFor(2000)});

The first test is to check if the form has been rendered correctly.

test('form loads correctly', async () => {const form = (await page.$('form')) ? true : false;const h3 = await page.$eval('h3', el => el.textContent);expect(form).toBe(true);expect(h3).toBe('Log In');});

Add the afterAll hook to close the browser when the test is done running

afterAll(async () => {browser.close();});

To run the test, make sure your React App is running or else the test will fail because Puppeteer will go to http://localhost:3000/ to run the end-to-end tests

npm test

You should get a response like this in your console

To test the form validations

Create selectors variables for the email, password input fields and the login button so that we can access anywhere in the file

const emailSelector = '[data-testid="email"]';const passwordSelector = '[data-testid="password"]';const buttonSelector = '[data-testid="submit"]';

Test for invalid email

test('returns invalid email', async () => {await page.waitForSelector(emailSelector);await page.click(emailSelector);await page.keyboard.type('ben.com');await page.waitForSelector(passwordSelector);await page.click(passwordSelector);await page.keyboard.type('14456678');await page.waitForSelector(buttonSelector);await page.click(buttonSelector);const error = await page.$eval('.error', el => el.textContent);expect(error).toBe('Invalid email address');});

Test for invalid password

test('returns invalid password', async () => {
await page.waitForSelector(emailSelector);// clear the input fieldawait page.$eval(emailSelector, el => (el.value = ''));await page.click(emailSelector);await page.keyboard.type('ben@gmail.com');await page.waitForSelector(passwordSelector);// clear the input fieldawait page.$eval(passwordSelector, el => (el.value = ''));await page.click(passwordSelector);await page.keyboard.type('144');await page.waitForSelector(buttonSelector);await page.click(buttonSelector);
const error = await page.$eval('.error', el => el.textContent);expect(error).toBe('Password length should not be less than 6 and more 20');});

Test for successful login. It should take us to the new page

test('return successful', async () => {await page.waitForSelector(emailSelector);// clear the input fieldawait page.$eval(emailSelector, el => (el.value = ''));await page.click(emailSelector);await page.keyboard.type('example@me.com');await page.waitForSelector(passwordSelector);// clear the input fieldawait page.$eval(passwordSelector, el => (el.value = ''));await page.click(passwordSelector);await page.keyboard.type('144ben');await page.waitForSelector(buttonSelector);await page.click(buttonSelector);await page.waitFor(2000);const home = await page.$eval('.home p', el => el.textContent);expect(home).toBe('Welcome to our world');});

Here’s the full code

To learn more about Puppeteer, check Puppeteer official documentation https://github.com/puppeteer/puppeteer

--

--