Learn End-to-end Testing with Puppeteer

3D ad banner ad revenue ad revenues adobe XD Advanced advanced-css-tools advanced-css-tutorials AdvancedCSS AdvancedCSS-hub agency Agile Agile Development Ajax Alex Skill Kit Alexa Alexa skill AlexW Amazon Alexa amazon developer analytics Angelap angular AngularJS Animation anime.js ANN api apollo Appsflyer array methods artificial neural network Async async components automation Avocode AWS AWS Lambda axios b2b b2c baas background background eraser tool Banner banner ad Bannersnack bawmedia bem bitcoin black friday Blogs bootstrap bot browser testing Browsers build process bundler Business business success Canvas & SVG career Career Advancement CDN Chakra UI charting chat app chatbots ChatKit chrome chrome developer tools chrome extension chrome extensions chromium ciphering cli cli tools climate climate action clojure cloud hosting CloudFlare Cloudways cms CNN code challenge ColinI compiler components const assertions constructs content content delivery network context api convoluted neural network create react app cron job cross browser testing cross platform development cross-browser cryptocurrencies CSS CSS Architecture css blur css challenge css framework css frameworks css grid css modules CSS print css rem css typography CSS-in-JS CSS3 css3 transforms cssbattle.dev D3.js data visualization databases debugging decoupled cms deep linking delay Design Design & UX design career design handoff Detox dev environment developer tools DevOps devtools diagnostic analytics digit recognition digital agency digitalocean Discord discounts Docker Docker Containers E-commerce ECMAScript edge computing editor elastic em units employment end-to-end testing energy energy usage Entrepreneur Entrepreneurship environment erasing backgrounds es6 ES6 classes eslint Expo Express FaaS face detection face recognition fast wordpress themes Feathers Feathers.js figma flatfile flexible wordpress theme framework Frameworks freelancing functional programming functions gatsby generators geolocation gitCS github github API Google Photos GraphCMS graphing graphql Growth Grunt Gulp haskell headless CMS hooks hosting HTML HTML & CSS html preprocessor HTML5 HTML5 Dev Center https://www.sitepoint.com/windows-linux-subsystem-2-windows-terminal IAAS IDE Illustration image optimization immutability ionic IP2Location jade jamesh JavaScript javascript framework javascript frameworks javascript tooling Jest job joelf jQuery jquery get url params jquery string functions jquery4u js js framework JS tooling Keras keycdn lambdatest launch checklist Layout learn-advanced-css learn-modernjs Learn-Node-JS learn-vue Lift linux linux containers location tracking LouisL Managed managed hosting mariap marvel MBaaS mekanism mind map mind mapping mindmapping Mobile mobile attribution Mobile Design modernjs modernjs-hub modernjs-tools modules monday mongodb MTCNN multi-threading natural language processing Navigation navigation library nest Next.js nilsonj node node version manager node-hub Node-JS-Tools Node-JS-Tutorials Node.js nodejs noops npm nvm objects octobercms Offers online publishing PaaS Package Management package manager pause Percy Performance Photography & Imagery Photoshop Photoshop Tutorials & Articles pip portfolio portfolio builders preprocessors prettier print styles Prisma Private Class Fields product design Profitability Programming PubNub Pug Puppeteer Pusher python python job Quasar query strings quick-tip quote builders Raw JavaScript React react components React Hooks React Hooks Form React native reactive Reactive Programming reactive web apps read offline Reat native elements Recurring Payments recursive types RedBox redux rem units remote work remote work tips removing backgrounds resilient Resources responsive REST restful api Review SaaS sampling sass Scss self sencha serverless serverless computing shared hosting sharing state sharpen side project siteground sketch slashdata sleep Software sorting specifications speech recognition speech recognition api sponsored state state management static module bundler StudioWorks Styled Components styling React components survey sustainability svelte sympli Tailwind task runner telegram bots Template engine Testing text to speech Themes Tic Tac Toe Tinder toggle Tolerance tooling tooling anxiety tools Tools & Libraries transformations TypeScript Ubuntu UI UI Design Usability user experience user research UX ux issues vanilla javascript VGGFace2 virtual machine visual testing voice recognition vps vue Vue CLI vue dev environment vue-hub vue-tutorials vue.js vuetify vuex wait WatermelonDB Web Web Design web hosting Web Hosting & Domains Web standards web workers webpack website builders website performance WebSockets windows windows 10 home Windows Subsystem for Linux Windows Terminal wix women women in tech WordPress wordpress themes WordPress theming work workers workflow working remotely workplaces WPEngine WSL WSL2 YellowBox Zeplin

End-to-end Testing with Puppeteer

Puppeteer is a Node library which provides a high-level API to control Chrome or Chromium over the DevTools Protocol. Puppeteer runs headless by default, but can be configured to run full (non-headless) Chrome or Chromium.

In this tutorial, we’ll learn what testing is, the different types of testing, and then we’ll use Puppeteer to perform end-to-end testing on our application. By the end of this tutorial, you should be able to end-to-end test your apps easily with Puppeteer.

Prerequisites

For this tutorial, you need a basic knowledge of JavaScript, ES6+ and Node.js.

You must also have installed the latest version of Node.js.

We’ll be using yarn throughout this tutorial. If you don’t have yarn already installed, install it from here.

You should also know the basics of Puppeteer. To understand the basics of Puppeteer, check out this simple tutorial.

To make sure we’re on the same page, these are the versions used in this tutorial:

  • Node 13.3.0
  • npm 6.13.2
  • yarn 1.21.1
  • puppeteer 2.0.0
  • create-react-app 3.3.0

Introduction to Testing

In simple terms, testing is a process to evaluate the application works as expected. It helps in catching bugs before your application gets deployed.

There are four different types of testing:

  1. Static Testing: uses a static type system like TypeScript, ReasonML, Flow or a linter like ESLint. This helps in capturing basic errors like typos and syntax.
  2. Unit Testing: the smallest part of an application, also known as a unit, is tested.
  3. Integration Testing: multiple related units are tested together to see if the application works perfectly in combination.
  4. End-to-end Testing: the entire application is tested from start to finish, just like a regular user would, to see if it behaves as expected.

The testing trophy by Kent C Dodds is a great visualization of the different types of testing:

Testing Trophy - Kent C Dodds

The testing trophy should be read bottom-to-top. If you perform these four levels of testing, you can be confident enough with the code you ship.

Now let’s perform end-to-end testing with Puppeteer.

End-to-end Testing with Puppeteer

Let's bootstrap a new React project with create-react-app, also known as CRA. Go ahead and type the following in the terminal:

$ npx create-react-app e2e-puppeteer

This will bootstrap a new React project in a e2e-puppeteer folder. Thanks to the latest create-react-app version, this will also install testing-library by default so we can test our applications easily.

Go inside the e2e-puppeteer directory and start the server by typing the following in the terminal:

$ cd e2e-puppeteer
$ yarn start

It should look like this:

React Init

Our App.js looks like this:

import React from 'react';
import logo from './logo.svg';
import './App.css';

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

export default App;

We’ll be testing the App.js function and the code will be written in App.test.js. So go ahead and open up App.test.js. It should have the following content:

import React from 'react';
import { render } from '@testing-library/react'; // 1
import App from './App';

test('renders learn react link', () => { // 2
  const { getByText } = render(<App />); // 3
  const linkElement = getByText(/learn react/i); // 4
  expect(linkElement).toBeInTheDocument(); // 5
});

Here's what's happening in the code above:

  1. We import the render function from the @testing-library/react package.
  2. We then use the global test function from Jest, which is our test runner installed by default through CRA. The first parameter is a string which describes our test, and the second parameter is a function where we write the code we want to test.
  3. Next up, we render the App component and destructure a method called getByText, which searches for all elements that have a text node with textContent.
  4. Then, we call the getByText function with the text we want to check. In this case, we check for learn react with the case insensitive flag.
  5. Finally, we make the assertion with the expect function to check if the text exists in the DOM.

This comes by default when we bootstrap with CRA. Go ahead and open up another terminal and type the following:

$ yarn test

When it shows a prompt, type a to run all the tests. You should now see this:

React Init Test

Now let's test this application with end-to-end testing.

Testing the Boilerplate with Puppeteer

Go ahead and install puppeteer as a dev dependency by typing the following in the terminal:

$ yarn add -D puppeteer

Now open up App.test.js and paste the following:

import puppeteer from "puppeteer"; // 1

let browser;
let page;

// 2
beforeAll(async () => {
  browser = await puppeteer.launch({
    headless: false
  });
  page = await browser.newPage();
  await page.goto("http://localhost:3000/");
});

// 3
test("renders learn react link", async () => {
  await page.waitForSelector(".App");

  const header = await page.$eval(".App-header>p", e => e.innerHTML);
  expect(header).toBe(`Edit <code>src/App.js</code> and save to reload.`);

  const link = await page.$eval(".App-header>a", e => {
    return {
      innerHTML: e.innerHTML,
      href: e.href
    };
  });
  expect(link.innerHTML).toBe(`Learn React`);
  expect(link.href).toBe("https://reactjs.org/");
});

// 4
afterAll(() => {
  browser.close();
});

This is what we're doing in the code above:

  1. Firstly, we import the puppeteer package and declare some global variables, browser and page.
  2. Then we have the beforeAll function provided by Jest. This runs before all tests are run. Here, we launch a new Chromium browser by calling puppeteer.launch(), while setting headless mode to false so we see what's happening. Then, we create a new page by calling browser.newPage() and then go to our React application's URL http://localhost:3000/ by calling the page.goto() function.
  3. Next up, we wait for the .App selector to load. When it loads, we get the innerHTML of .App-header>p selector by using the page.$eval() method and compare it with Edit src/App.js and save to reload.. We do the same thing with the .App-header>a selector. We get back innerHTML and href and then we compare them with Learn React and https://reactjs.org/ respectively to test our assertion with Jest's expect() function.
  4. Finally, we call the afterAll function provided by Jest. This runs after all tests are run. Here, we close the browser.

This test should automatically run and give you the following result:

E2E Test Puppeteer Basic

Let's go ahead and make a counter app.

The post Learn End-to-end Testing with Puppeteer appeared first on SitePoint.

Original Article

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.