React E2E Testing: Getting Started Guide

This tutorial helps getting started with React end to end testing using popular tools like Cypress and Jest.

OVERVIEW

Your application will fail if you only perform unit testing.

The statement above holds when your team relies only on unit testing and ignores the importance of end-to-end testing in software applications.

In frontend engineering, end-to-end testing is vital as it simulates the user's action and discovers errors, bugs, and defects even before your real users use the application.

In this React end to end testing tutorial, we will explore how to get started with React end to end testing using popular tools like Cypress and Jest. We will also elucidate the best practices and industry-standard principles in writing and executing enterprise-level and scalable end-to-end testing for React applications.

What is React?

React is one of the most popular JavaScript libraries for building complex and dynamic web applications. As your application grows in size and complexity, testing becomes an essential part of the development process. End-to-end testing is a valuable way to ensure that your application works as intended from the user's perspective.

What is end-to-end testing?

End-to-end (E2E) testing is a type of software testing that ensures the application behaves as expected from the user's perspective. It involves testing the entire software stack from the front end to the back end, including all the external systems and integrations. E2E testing can help identify broken links, missing elements, and incorrect functionality.

Why use end-to-end testing?

As a software engineer, it is important to understand the various testing approaches and when to use them. One testing approach that is becoming increasingly popular in the software development industry is end-to-end testing. Below are some reasons why end-to-end testing is essential for ensuring software quality.

  • Detects Integration Issues
  • One of the primary benefits of end-to-end testing is that it helps detect integration issues. When multiple components of an application or system are developed separately, there is a risk of integration problems when they are brought together. End-to-end testing helps identify these issues before they reach production, reducing the risk of application failure.

  • Mimics Real User Scenarios
  • End-to-end testing also mimics real user scenarios, providing a more accurate representation of how the application or system will function in the real world. It tests the entire system, including the user interface, backend processes, and third-party integrations, ensuring that all components work together seamlessly.

  • Helps Ensure User Satisfaction
  • By testing the entire system, end-to-end testing helps ensure user satisfaction. It identifies any issues that may cause frustration or dissatisfaction among users, such as slow response times or incorrect data display. By detecting these issues early, developers can make necessary changes to improve user experience.

  • Enhances Software Quality
  • End-to-end testing enhances software quality by ensuring that all components of the application or system work together as intended. It identifies issues that may be missed by other testing approaches, such as unit testing, and helps ensure that the final product is of high quality.

  • Reduces Risk of Bugs in Production
  • End-to-end testing reduces the risk of bugs in production by identifying issues before they reach the end user. This helps reduce the cost and effort required to fix issues post-release, minimizing user impact.

In addition, end-to-end testing is an essential approach for ensuring software quality. By incorporating end-to-end testing into the testing process, software development teams can improve the overall quality of the final product and ensure a positive user experience.

What is the need for React testing?

It's essential to ensure that the code we produce is of the highest quality and is free from any bugs or issues. To achieve this, we need to have a robust testing strategy, including testing our React components thoroughly. React testing is necessary for the following reasons:

Note: You can learn more about it through this React testing tutorial.

  • Ensures Functionality
  • React testing ensures that the components we develop to function as intended. By testing each component thoroughly, we can ensure that all features and functionality are working correctly.

  • Prevents Bugs and Errors
  • Testing helps us prevent bugs and errors from occurring in our code. We can catch issues early in the development process, which helps reduce the time and effort required to fix them later on.

  • Improves Code Quality
  • By testing our code, we can ensure that it meets the required quality standards. This includes ensuring that it is maintainable, scalable, and follows industry best practices.

  • Enhances User Experience
  • Testing can help us enhance the user experience by ensuring that the components are easy to use, intuitive, and provide a seamless experience for the end-users.

  • Supports Code Refactoring
  • Testing can help us with code refactoring. We can modify code confidently, knowing that we have tests to ensure we haven't broken anything.

What to test in a React application?

As a software engineer, when testing a React application, it's essential to consider what to test to ensure the code is robust and reliable. Here are the critical components to consider when testing a React application:

  • Component Rendering and Functionality
  • Testing component rendering and functionality are essential to ensure that the application's user interface (UI) is working correctly. This testing ensures that the components render as expected and the user interactions function correctly.

  • User Interaction and Behavior
  • Testing user interaction and behavior is crucial for ensuring the application responds to user input as expected. Testing user interactions involves simulating user input and verifying that the application responds as intended. It is essential to ensure that the user's interaction with the application is smooth and without any issues.

  • State Management
  • Testing state management is essential to ensure that the application's state is being managed correctly. Testing the application state involves verifying the application updates the state as expected and that the user interface updates accordingly. Libraries like Redux and MobX can be used to manage the application state and test it.

  • Network Requests
  • Testing network requests is essential to ensure the application communicates with the server as expected. Testing network requests involves simulating network requests and verifying that the application sends and receives data correctly. Libraries like Axios and Mock Service Worker can be used to test network requests.

  • Integration
  • Testing integration involves verifying that different components of the application work together seamlessly. This testing ensures that the application is functioning as intended and that all components are interacting correctly. Integration testing can be done using libraries like Cypress and Enzyme.

Furthermore, by testing all of these components, we can ensure that the application is robust, reliable, and provides an excellent user experience.

Note

Note : Perform React end to end testing across 3000+ browsers and operating systems. Try LambdaTest Now!

Tools for React end to end testing

Performing React end to end testing requires different software and tools such as Cypress, Playwright, TestCafe, etc.

Performing React end to end testing requires different software and tools such as Cypress, Playwright, TestCafe, etc.

However, these tools are already developed and tested for efficiency and effectiveness when it comes to E2E testing large and enterprise-ready applications, so there's no need to reinvent the wheel.

Below are some of the categories of tools needed to aid your React testing.

Mocking Library

To perform React end to end testing, you need to use a mocking library to aid in focusing only on testing the most important thing while mocking or using fake data for the less important aspect of the component. Mocking libraries can also help accelerate the speed of your application by introducing mocked data instead of simulating real user action, which may result in slow testing.

Test Runner

A test runner is a software that helps run and execute your React end to end test suits. You can run your test suites by selecting individual tests or groups of test cases. The test runner library generates reports after running the test to indicate the success or failure state of the test.

Assertion Library

When performing any software testing, it is required to test the outcome of a conducted test, such as checking if the button is clickable when a page is loading or if the length of a square is equal to the breadth. This is where assertion libraries come to play.

Below are the top three React end to end testing tools based on their popularity, usage, and GitHub statistics:

  • Cypress: Cypress is a popular testing framework for React end to end testing. It provides a user-friendly experience and allows developers to write tests using JavaScript. It has a rich set of features and runs tests in the browser, which makes debugging more accessible. Cypress has over 43,000 Stars on GitHub, making it one of the most popular automation testing tools.
  • Jest: Jest is another popular testing framework used for React end to end testing. It is a powerful tool that offers features such as code coverage, snapshot testing, and mocking. Jest has over 42,000 Stars on GitHub, making it a widely used and popular choice for testing React applications.
  • Puppeteer: Puppeteer is an automation testing framework for React end to end testing that provides a high-level API for controlling headless Chrome or Chromium browsers. It offers features such as screenshots, PDF generation, and tracing. Puppeteer has over 83,000 Stars on GitHub, making it a popular choice for testing React applications.

In short, Cypress, Jest, and Puppeteer are three of the most popular React end to end testing tools based on their popularity, usage, and GitHub stats. Developers can choose any of these frameworks depending on their needs and preferences.

Getting started with React end to end Testing

We will create a simple React Task Tracker project for this demo. This React project allows users to add tasks, mark them as done, and delete tasks.

Follow these steps to create a new React project:

  • Install a new React project using this command:
  • npm create vite@latest react-task-tracker -- --template react
  • Navigate into your newly created directory and open it in your favorite code editor (using VSCode here)
  • cd react-task-tracker
    code .
  • Next, install all the required dependencies with the following command:
  • npm install
  • Next, you can preview your newly installed React project with the following command:
  • npm run start
  • If everything works as expected, open the App.js file and replace it with the code snippet below:
  • import { useState } from "react";
    import AddTask from "./components/AddTask";
    import Header from "./components/Header";
    import Tasks from "./components/Tasks";
    function App() {
     const [tasks, setTasks] = useState([
       {
         id: 1,
         text: "Doctors Appointment",
         day: "Feb 5th at 2:30pm",
         reminder: true,
       },
       {
         id: 2,
         text: "Meeting at school",
         day: "Feb 5th at 1:30pm",
         reminder: true,
       },
       {
         id: 3,
         text: "Food Shopping",
         day: "Feb 5th at 2:30pm",
         reminder: false,
       },
     ]);
    
     const [showAddTask, setShowAddTask] = useState(false);
     // Delete a task
     const deleteTask = (id) => {
       setTasks(tasks.filter((task) => task.id !== id));
     };
    
     // Add task
     const addTask = (task) => {
       const id = Math.floor(Math.random() * 10000) + 1;
       setTasks([...tasks, { ...task, id }]);
     };
    
     // Toggle reminder
     const toggleReminder = (id) => {
       setTasks(
         tasks.map((task) =>
           task.id === id ? { ...task, reminder: !task.reminder } : task
         )
       );
     };
    
     return (
       <div className="container">
         <Header onShowAddTask={() => setShowAddTask(!showAddTask)} />
         {showAddTask && <AddTask onAddTask={addTask} />}
         {tasks.length > 0 ? (
           <Tasks tasks={tasks} onDelete={deleteTask} onToggle={toggleReminder} />
         ) : (
           "No tasks found"
         )}
       </div>
     );
    }
    
    export default App;

Code Walkthrough

Let's walk through the nitty-gritty of this code snippet.

Step 1 – Importing and initializing React.

In this step, we imported all the required packages and initialized the tasks array for default tasks to be displayed.

importing-and-initializing-react

We created a Tasks array and showAddTask boolean using React useState to store all our tasks and toggle between Add task windows.

Step 2 – Creating the delete task functionality.

We created the delete task functionality that takes the ID of a particular task and filters through the array to remove it.

Creating the delete task functionality

Step 3 – Creating the add task functionality.

We created the add task functionality that takes a task object and pushes it to the array of tasks created above.

add task functionality

Step 4 – Creating the marked functionality.

This is the marked functionality that marks a task as completed or not completed when the "set reminder" checkbox is toggled.

marked functionality

Step 5 – Rendering the components.

This code snippet renders all the components that use all the functionalities discussed above:

Rendering the components

In addition, each of the components in the code snippet above can be found inside the GitHub repository for this project, which you can clone directly from here:

If everything is properly set up, you should be presented with a demo react task tracker application as shown below:

task-tracker

Setting up Cypress

Cypress is a JavaScript testing framework that allows you to write end-to-end tests that run in the browser.

To set up Cypress, you need to install it using npm, a package manager for Node.js. Open a terminal window and run the following command:


npm install cypress --save-dev 
terminal-command-react

Once you have successfully installed Cypress, use this command to open and configure it.


npx cypress open 

You can follow the instructions from the Cypress official website and select E2E testing for this project. Next, create a new folder called tests/e2e inside the test src folder.

Lastly, open the newly created cypress.config.js configuration file in the root directory and replace it with the following code snippet.


const { defineConfig } = require("cypress");

module.exports = defineConfig({
component: {},

env: {
// HINT: here we read these keys from .env file, feel free to remove the items that you don't need
baseUrl: process.env.FE_URL ?? "http://localhost:3000",
},

e2e: {
supportFolder: false,
supportFile: false,
specPattern: "src/tests/e2e/**/*.spec.js",
// eslint-disable-next-line no-unused-vars
setupNodeEvents(on, config) {
// implement node event listeners here
},

baseUrl: process.env.FE_URL ?? "http://localhost:3000",
},
}); 

The most important configuration here is setting the default location for Cypress to locate the E2E test files using specPattern and the baseURL to run the test.

Creating test files

Next, create a new file inside the src/tests/e2e folder called tasks.spec.js and paste in the following test codes:


/* eslint-disable jest/valid-expect */
/* eslint-disable testing-library/await-async-utils */
/* eslint-disable no-undef */

const afterLoginFunction = () => {
cy.visit('${Cypress.env("baseUrl")}');
};

describe("Tasks tests", () => {
beforeEach(() => {
afterLoginFunction();
cy.wait(5000);
});

// Add task

it("can add a new task", () => {
cy.get("header .btn").click();
cy.wait(1000);

cy.get('.add-form input[placeholder="Add Task"]').type("Cypress Task 1");
cy.get('.add-form input[placeholder="Add Day & Time"]').type(
"March 18 at 4:00pm"
);

cy.get(".add-form").then(() => {
cy.get('.add-form input[type="submit"]').click();
cy.wait(1000);
cy.get(".task h3").each(($el) => {
return cy.contains("Cypress Task 1");
});
});
});

// Delete task
it("can delete a task", () => {
cy.get(".task h3").then(() => {
cy.get(".task h3 svg").first().click();

cy.wait(1000);

cy.get(".task")
.each(($el) => {
return $el;
})
.then(($el) => expect($el).to.have.length(2));
});
});

// Mark task
it("can mark a task", () => {
cy.get(".task:first ").then(() => {
cy.get(".task").last().dblclick();

cy.wait(1000);

cy.get(".reminder")
.each(($el) => {
return $el;
})
.then(($el) => expect($el).to.have.length(3));
});
});
});

Code Walkthrough

Let's walk through the nitty-gritty of this task file.

Step 1 – Visiting the URL.

In this step, we ask Cypress to visit the base URL and set everything up for testing the user's action on the page.


users-action

Step 2 – Testing the Add Task action.

Next, we test out the Add Task functionality of our application since it is crucial and a way for users to create new tasks they want to perform.


add-task-action

The code snippet above uses Cypress get function from the global cy object to retrieve page elements based on the queries provided. For instance, we ask Cypress to locate a button inside the header element with a class of button and click it.

Using the get function in combination with other Cypress functions, we can retrieve and perform actions on any HTML element just as your users would.

Step 3 – Testing the Delete Task action.

Next, we test out the Delete Task functionality of our application to see if we can delete tasks from the list of available tasks.


delete-task-action

Step 4 – Testing the Marked Task action.

Next, we test out the Marked Task functionality of our application to see if we can mark tasks as completed or not.


marked-task-action

Running your E2E test suites

Finally, we have everything set up and all our test cases written. Let's run the test to make sure everything is passing as expected.

To run your test, open your package.json file and add the following code to the scripts section:


"test:e2e": "cypress open --e2e",
    "test:e2e:ci": "cypress run --e2e", 

The first line opens a new Cypress window and asks you to choose a browser to run your test, choose Electron and watch your test case running one after the other.

However, if you want to run the test with the terminal or using any automated pipeline like LambdaTest, use the second line, which will run your test using the CLI.

...

LambdaTest is a digital experience testing platform that lets you perform automation testing with popular testing frameworks, including Cypress and Jest, on an online browser farm of 3,000+ different browsers and operating systems.

Subscribe to the LambdaTest YouTube Channel and stay updated with the latest tutorial around Selenium testing, Cypress testing, and more.

Now enter the following command in your terminal to run your test:


npm run test:e2e

If everything works as intended, you should be greeted with a successful test, as shown in the short video.

successful test

If your test cases are not passing, you can revisit your code or check the repository for the correct code base.

Summary

This React end to end testing tutorial provides a detailed guide to beginners on how to get started with React end to end testing using popular testing frameworks such as Cypress and Jest. The guide is demonstrated with a simple Task Tracker app example, and the blog provides detailed code snippets for building and testing the app.

Frequently asked questions

  • General ...
Which testing is end-to-end testing?
End-to-end testing is a comprehensive testing approach that verifies the entire software system's functionality and behavior from start to finish. It involves testing the software application across multiple components and systems to ensure that all integrated parts work seamlessly together and meet the intended requirements. End-to-end testing validates the flow of data and interactions between different subsystems, simulating real-world user scenarios to identify any issues or gaps in the system.
Can I use Jest for end-to-end testing?
While Jest is primarily designed for unit testing in JavaScript, it is not typically used for end-to-end testing. For end-to-end testing, other frameworks and tools are generally more suitable. Examples include Cypress, Selenium WebDriver, Puppeteer, and Playwright. These frameworks are specifically designed to simulate real user interactions, navigate through web applications, and validate the entire application flow across multiple components and systems. However, Jest can still be used in conjunction with other tools to cover different layers of testing. For example, you can use Jest for unit testing and combine it with Cypress for end-to-end testing to achieve comprehensive test coverage for your application.
What is an end-to-end test for react native?
In React Native, end-to-end testing refers to the process of testing the entire application's functionality, user flows, and interactions across various components and screens. It involves simulating real-world scenarios to validate the behavior and performance of the application as a whole.

Did you find this page helpful?

Helpful

NotHelpful

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud