ASSIST Software ReactJS Testing with Jest and Enzyme, coding
1. The importance of writing tests in projects
If you ask someone what the role of a developer is, their answer would probably be to write code for an application. This is partially true. A developer picks a ticket from a list, analyzes and writes code for it, then assigns it to a person that is responsible for the final validation.
The point is that the developer is responsible for the code as well. How can a developer validate that code is written well before passing it? By testing it, of course!
What if I told you that a developer should test their code before assigning a ticket to a QA engineer? The thought that probably crosses your mind is that you do not have time to test your code. What if you could test your code by writing code for it? Would you then be more interested?
There are many benefits of testing your code before you send it to the QA team: it prevents regression and it reduces the number of bugs returned, so the QA Engineer will allocate less time for testing. Unit tests should cover more scenarios to reduce the probability of breaking the application.
2. What are Jest and Enzyme?
There are many libraries for unit testing, but Jest is a JavaScript testing framework, and it can be integrated with projects that use the JavaScript language.
Why should you try testing with Jest and what are the best practices of the biggest companies that need to test their code?

Facebook ReactJS tests are done with Jest but they aren't the only ones using it. Many other companies love it and some of them are high-profile names. Facebook, Instagram, and Revolut use Jest to test their code, which makes some people deem it the best ReactJS testing framework. 
Airbnb uses it successfully as well but they have another ReactJS Testing Utility to pride themselves on. Airbnb has developed its own testing utility (before delivering it to a third party) and, from what we know, the company is still using it for testing today.  Airbnb is working with Enzyme, a testing utility that can be employed easily with three useful functions:
⦁ render -> This is used when you want to handle HTML. It outputs the rendered HTML of the component. You have no access to React lifecycle methods.
⦁ shallow -> This renders the component without the child components inside it. You have access to React lifecycle methods.
⦁ mount -> This is used to interact with the component and the child components. You have access to React lifecycle methods.
3. Installation and configuration
Jest is already set up when a new ReactJS project is created. In order to create a React project, run this command: npx create-react-app [project name]. 
After the project installation is finished, navigate to the project folder. The following need to be installed into the project:
⦁ Enzyme
⦁ enzyme-adapted-react-16 -> The role of this adapter is to help the enzyme work with your React version. To check which version is compatible with your React version, you can check on the official website.
⦁ enzyme-to-json  -> This helps to serialize snapshots with Jest, and it will be used in  Section 5. 
The command to install all these libraries is npm install enzyme @wojtekmaj/enzyme-adapter-react-17 enzyme-to-json --save-dev
Currently, there is no official adapter for React v17. For this project, an unofficial version was used: https://www.npmjs.com/package/@wojtekmaj/enzyme-adapter-react-17
In order to start the project, run the npm start command.
The next step is to configure Enzyme to use the adapter. In the setupTests.js file, add the following lines:

import "@testing-library/jest-dom";

import { configure } from "enzyme";
import Adapter from "@wojtekmaj/enzyme-adapter-react-17";

configure({ adapter: new Adapter() });

Figure 1 – Configuration of Enzyme to use the adapter
 

4. Code Testing
Before starting to write unit tests in an application, it is a good practice to think about some code test cases. Having an idea of what needs to be tested can help you group them into describe blocks. The tests are written inside the block using the following methods: test() and it(). Both methods can be used but method it() is aliased by test().
The tests should be written in such a way that they are easy to understand. In the describe block, the action is to "do something", so the it() method can be used multiple times.
The tests presented in the following subchapters are written in order to test the functionality of a form. All the tests were written into the App.test.js file, but in a real project, it is recommended to create them in the folder of the component that is going to be tested. The files where the tests are written can be identified by the extension [filename].test.js
To check if all test functions are passing, run the npm test command. The tests run in watch mode so every time a change is made, they automatically run in parallel.
4.1 Components rendering
The first group of tests checks if the components are rendering. As previously mentioned, the tests are grouped in a describe block, giving them a suggestive name.
It can be tested whether an entire component or just a specific part of it is rendered. The first three tests check if the React components rendered without crashing.
The next test checks if the title is rendered in the App component. It is expected for the wrapper to contain the h1 element including the text. As a validation, the toBe() method  is used.
There are multiple ways to validate whether specific elements are rendered. The most common methods are toBe() and toEqual(). The difference between these methods is that the first one is built to deal with primitive values like numbers and strings, while the second one deals with objects and arrays.
To check if all the form inputs were rendered, the inputs should be located by the name property using the find() method. For each input with a specific name, the toHaveLength() method  used and one item for each specific input is expected to be found.
The last test from this block checks if the text is formatted correctly. The text is extracted using the find() method from Enzyme to locate the node. The text() method returns the rendered text. 

describe("The components are rendered", () => {
  it("renders App component without crashing", () => {
    shallow(<App />);
  });

  it("renders Form component without crashing", () => {
    shallow(<Form />);
  });

  it("renders FormList component without crashing", () => {
    shallow(<FormList />);
  });

  it("renders title without crashing", () => {
    const wrapper = shallow(<App />);

    const header = <h1>Become a volunteer</h1>;
    expect(wrapper.contains(header)).toBe(true);
  });

  it("renders form inputs", () => {
    const wrapper = shallow(<Form />);

    expect(wrapper.find('input[name="volunteerName"]')).toHaveLength(1);
    expect(wrapper.find('input[name="hours"]')).toHaveLength(1);
    expect(wrapper.find('select[name="jobTitle"]')).toHaveLength(1);
  });

  it("renders submit button without crashing", () => {
    const wrapper = shallow(<Form />);

    const label = wrapper.find("#submit-button").text();
    expect(label).toBe("Submit");
  });
});

Figure 2 – Checking components rendering.

4.2 Passing props
The next describe group checks if components accept props. In order to receive data from an application, the Axios library is used to initiate API calls. JSON Server is used as a fake API for the mock data, which is kept in the db.js file. At the beginning of the testing file, the list of forms is imported from the db.js file.
For the first test, the FormList component is mounted and the forms are sent as a property. By using the toEqual() method, you can check if the wrapper received the forms’ props.
The second test goes through each form and using the toHaveProperty() method checks if it received all the properties (id, volunteerName, hours, jobTitle). 

import { forms } from "../db.json";

describe("FormList is passing props", () => {
  it("accepts props", () => {
    const wrapper = mount(<FormList forms={forms} />);
    expect(wrapper.props().forms).toEqual(forms);
  });

  it(`should have all properties`, () => {
    const wrapper = mount(<FormList forms={forms} />);
    const renderedForms = wrapper.props().forms;
    for (let i = 0; i < renderedForms.length; i += 1) {
      expect(renderedForms[i]).toHaveProperty("id");
      expect(renderedForms[i]).toHaveProperty("volunteerName");
      expect(renderedForms[i]).toHaveProperty("hours");
      expect(renderedForms[i]).toHaveProperty("jobTitle");
    }
  });
});

Figure 3 – Checking if the component accepted props.

4.3 Events

On a form, actions can be done using event handlers. Figure 4 shows some examples of how to test the events such as changing the input’s value, submitting the form, and resetting the form. The change event is simulated for all the form inputs.

Following the DRY principle, the logic of simulating the change action of an input was extracted into the simulateOnChangeInput() function. For each input, it’s expected that the new values will be sent to the change method.

After the inputs have been filled with the given values, the click event on the reset button is simulated. The new values that are expected to be received from the inputs are the default ones. 


const simulateOnChangeInput = (wrapper, inputSelector, newValue) => {
  const input = wrapper.find(inputSelector);
  input.simulate("change", {
    target: { value: newValue },
  });

  return wrapper.find(inputSelector);
};

describe("The events are working", () => {
  it("fill the form with values and then reset the form", () => {
    const wrapper = shallow(<Form />);

    const updatedNameInput = simulateOnChangeInput(
      wrapper,
      "#volunteerName-input",
      "Endzela Gaye"
    );
    const updatedHourInput = simulateOnChangeInput(
      wrapper,
      "#hours-input",
      "2"
    );
    const updatedJobTitleInput = simulateOnChangeInput(
      wrapper,
      "select",
      "Food supply"
    );
    
    expect(updatedNameInput.props().value).toBe("Endzela Gaye");
expect(updatedHourInput.props().value).toBe("2");
    expect(updatedJobTitleInput.props().value).toBe("Food supply");

    wrapper.find("#reset-button").simulate("click");

    expect(wrapper.find("#volunteerName-input").props().value).toBe("");
    expect(wrapper.find("#hours-input").props().value).toBe("");
    expect(wrapper.find("#job-input").props().value).toBe("Raising funds");
  });
});

Figure 4 – Filling the form with values and then resetting it

4.4 Mock functions
A mock function is a fake method that will give you some predefined results. It will not run the actual method code; instead, it will load up the call. Transforming it into a mock allows us to “spy” on the function calls.
The mock method will call the method that we want to spy on, and check if the behavior of it corresponds to what we are expecting. 
To create a fake method, jest.fn() is used:

describe("The events are working", () => {
  it("The form is submitted when the click event is fired by simulated click on the submit button", () => {
    const mockCallBack = jest.fn();

    const wrapper = shallow(<Form onSubmit={mockCallBack()} />);

    wrapper.find("#submit-button").simulate("click");
    expect(mockCallBack).toHaveBeenCalledTimes(1);
  });
});

Figure 5 – Submitting the form

In the example above, the form is wrapped and the onSubmit() method is passed to it. After that, the click event is simulated on the submit button and it is expected that the mock method is called once. To check how many times a method has been called, the toHaveBeenCalledTimes() method from Jest is used.
5. Snapshot Testing
The role of snapshot testing is to check if the elements are in the right position in the user interface. To make sure that elements will not be changed accidentally, a snapshot can be done that retains the rendered component at a certain time.
To convert the Enzyme wrapper to a format compatible with the Jest snapshot, the toJson() helper is used, which is provided by the enzyme-to-json library.

describe("Snapshot", () => {
  it("matches App the snapshot", () => {
    const wrapper = mount(<App />);
    expect(toJson(wrapper)).toMatchSnapshot();
  });
});

Figure 6– Checking if the snapshots are matching

When the tests are run for the first time, a folder named __snapshots__ is created where the snapshot is saved:

code text, test, jest, enzyme

Figure 7 – __snapshots__ file

Every time the tests are run, Jest compares the output of the component with the previous Jest snapshot and it will display an error message if there are any differences between them. (Figure 8)
 

Snapshot

Figure 8 – Differences between the snapshot and the rendered component

A message like this will appear: “1 snapshot failed from 1 test suite. Inspect your code changes or press `u` to update them.”

6. Ensure that your tests are written well!
After you’ve checked that your tests pass, a good practice is to then break them and check if they still pass.
code text, test, jest, enzyme
Figure 9 - Breaking a test
If the text that is expected to be received from the submit button is "Reset", an error will be displayed in the console where the name of the test that crashed is given together with the expected and received values.
7. Conclusion
I hope that you found this article helpful and that it’s given you a broad understanding of React JS unit testing. The libraries presented are very easy to use and come to the aid of developers to make the testing process as easy as writing an application and if Facebook tests with Jest and Airbnb test with Enzyme, that should be enough reason for you to also give it a try. 

Did you like this article and did you find it helpful? Leave us a message!
You can read more from the same author here: 

Share on:

I have read and understood the ASSIST Software website's Terms of Use and Privacy Policy.

Want to stay on top of everything?

Get updates on industry developments and the software solutions we can now create for a smooth digital transformation.

Frequently Asked Questions

1. Can you integrate AI into an existing software product?

Absolutely. Our team can assess your current system and recommend how artificial intelligence features, such as automation, recommendation engines, or predictive analytics, can be integrated effectively. Whether it's enhancing user experience or streamlining operations, we ensure AI is added where it delivers real value without disrupting your core functionality.

2. What types of AI projects has ASSIST Software delivered?

We’ve developed AI solutions across industries, from natural language processing in customer support platforms to computer vision in manufacturing and agriculture. Our expertise spans recommendation systems, intelligent automation, predictive analytics, and custom machine learning models tailored to specific business needs.

3. What is ASSIST Software's development process?  

The Software Development Life Cycle (SDLC) we employ defines the stages for a software project. Our SDLC phases include planning, requirement gathering, product design, development, testing, deployment, and maintenance.

4. What software development methodology does ASSIST Software use?  

ASSIST Software primarily leverages Agile principles for flexibility and adaptability. This means we break down projects into smaller, manageable sprints, allowing continuous feedback and iteration throughout the development cycle. We also incorporate elements from other methodologies to increase efficiency as needed. For example, we use Scrum for project roles and collaboration, and Kanban boards to see workflow and manage tasks. As per the Waterfall approach, we emphasize precise planning and documentation during the initial stages.

5. I'm considering a custom application. Should I focus on a desktop, mobile or web app?  

We can offer software consultancy services to determine the type of software you need based on your specific requirements. Please explore what type of app development would suit your custom build product.   

  • A web application runs on a web browser and is accessible from any device with an internet connection. (e.g., online store, social media platform)   
  • Mobile app developers design applications mainly for smartphones and tablets, such as games and productivity tools. However, they can be extended to other devices, such as smartwatches.    
  • Desktop applications are installed directly on a computer (e.g., photo editing software, word processors).   
  • Enterprise software manages complex business functions within an organization (e.g., Customer Relationship Management (CRM), Enterprise Resource Planning (ERP)).

6. My software product is complex. Are you familiar with the Scaled Agile methodology?

We have been in the software engineering industry for 30 years. During this time, we have worked on bespoke software that needed creative thinking, innovation, and customized solutions. 

Scaled Agile refers to frameworks and practices that help large organizations adopt Agile methodologies. Traditional Agile is designed for small, self-organizing teams. Scaled Agile addresses the challenges of implementing Agile across multiple teams working on complex projects.  

SAFe provides a structured approach for aligning teams, coordinating work, and delivering value at scale. It focuses on collaboration, communication, and continuous delivery for optimal custom software development services. 

7. How do I choose the best collaboration model with ASSIST Software?  

We offer flexible models. Think about your project and see which model would be right for you.   

  • Dedicated Team: Ideal for complex, long-term projects requiring high continuity and collaboration.   
  • Team Augmentation: Perfect for short-term projects or existing teams needing additional expertise.   
  • Project-Based Model: Best for well-defined projects with clear deliverables and a fixed budget.   

Contact us to discuss the advantages and disadvantages of each model. 

1. Is ASSIST Software a reliable company for custom engineering?

Absolutely. Our partners have given us great recommendations and reviews, leading us to win The Manifest Award for Most Reviewed Software Developers. Further proof comes from our 97% employee retention rate and ongoing client partnerships for over 8 years.  

2. Are the ASSIST Software Romanian software engineers certified?

Yes. 85% of our software programmers are certified.  

At a company level, ASSIST Software is certified and recognized by industry players such as Microsoft, AWS, Google Cloud, Adobe, Drupal, Fujitsu, ISTQB, and others.  

Our employee certifications are tremendously important as they reflect the shared commitment to long-term growth.

3. Why should I choose Romania for custom software development? 

Romania has become a significant player in custom software development, attracting businesses worldwide. Romania boasts the highest number of certified IT specialists in Europe and ranks sixth globally, surpassing even the US in tech specialists per capita.  

At ASSIST Software, what sets us apart is our team and our location: our engineers are certified, experienced, and flexible, while being in the +2 GMT time zone allows us to easily facilitate meetings with clients all over the world.

4. What team will work on my project, and where will it be located?

ASSIST Software's headquarters is in Romania, a prime country for software development outsourcing. Our 350+ software engineers speak English and have a deep passion for innovation.  

We provide regular project updates through reports, meetings, and online dashboards. Generally, you'll have access to a dedicated project manager who will be your point of contact for any questions or concerns.  

5. How much will my project cost me?

Our prices are competitive, and as per our working model, we guarantee you will be satisfied with the result. Frequent meetings, check-ins, and a great communication structure will ensure this outcome.   

Project costs depend on various factors, including complexity, scope, required technologies, and team size. We'll gather detailed information about your project during the initial consultation to provide a customized quote and we guarantee that you will be able to see the benefits of bespoke software.  

1. What technologies do you work with?

ASSIST Software tackles your projects with a robust tech stack. We build native and cross-platform mobile apps, craft user-friendly web experiences, and create stunning visuals. 

Our wide-ranging expertise starts from Java, Python, and JavaScript frameworks to cutting-edge solutions like AR/VR, blockchain, and AI/ML. We also manage databases, leverage cloud platforms, and ensure flawless project execution. We're your one-stop shop for exceptional software development from concept to deployment. You can view our expertise for more details.   

2. Are you experienced in AI/ML development?

Yes. We have extensive experience in data engineering and machine learning operations (MLOps). We can employ neural networks, computer vision, and AI models to benefit your ideas.   

You can trust our long-term experience with big data, NLP, and sentiment analysis, as over the past three years, we led a European security project with 15 partners focused on detecting radicalization on social media and the dark web.

3. Do you have a research and development department and work on European Projects?

We know R&D is crucial for businesses to stay competitive and thrive in dynamic markets. Successful R&D efforts lead to developing exceptional products or services, improved efficiency and effectiveness in operations, and enhanced market positioning.   

We have established solid partnerships with 160+ European research companies, universities, and research centers (e.g., Fraunhofer, TWI, University of Heidelberg, REWE Group, SINTEF, etc.) and have participated as technical partners in over 25 EU-funded projects.  

4. Besides custom software solutions, what other services do you offer?

  • Design Thinking for Breakthrough Products:  

    We craft user experiences that resonate. Our design process is an immersive collaboration, starting with workshops to uncover your vision and user needs. We conduct market research, analyze the competition, and guide you toward cutting-edge solutions in accordance with your business requirements.  

  • Digital Transformation to Reimagine Your Business:

    Digital transformation is nothing less than a strategic shift. We empower you to become more agile and data-driven, optimizing core processes for the digital age.  

  • Scale with Confidence as We Build for Growth:  

    We understand that business success and development mean new challenges. Our solutions are built to scale seamlessly, accommodating increasing user bases and data volumes without sacrificing performance or security.  

5. As a company, does ASSIST have its own software products?

Yes, ASSIST Software teams have been involved in designing and developing innovative products that address community needs. One such example is the web and mobile platform Autisma. This therapy assistant enables continued learning for children diagnosed with autism spectrum disorder.   

Our extensive knowledge of the Unity and Unreal engines has allowed us to develop two mobile games, Elly and the Ruby Atlas and Hooman Invaders, as well as various Unity Assets, such as the Real-Time Weather PRO and Easy Sky. These two Unity assets allow Unity developers to control the weather and sky in their projects.   

1. Is ASSIST Software hiring right now?

We are always looking for great people to join our team, whether you're a senior software engineer or a new talent seeking an IT career. Please check our careers page and contact us. Our HR department will contact you as soon as possible.   

2. Is ASSIST Software organizing internships?

Yes. Each year, we organize individual and group internships for students. Our long-term partnership with the Stefan cel Mare University of Suceava allows us to put together great events for students and help them get started in the industry. 

3. What type of learning culture does ASSIST Software encourage?

Our focus on innovation comes from a 'can do' attitude and the continuous learning we encourage our colleagues to pursue. We frequently organize workshops, learning sessions, presentations, and masterclasses. All these events are free and open to our colleagues and aim to support their professional and personal development. 

4. How does ASSIST Software focus on teamwork?

The key to stellar teamwork is the quality time we spend together. ASSIST employees and their families are frequently invited to participate in all activities. We encourage a healthy lifestyle by promoting and organizing hikes, bike riding sessions, marathons, volleyball, football and tennis matches, ping-pong championships, and many more.   

We show our care for the environment through reforestation campaigns and forest cleaning activities.   

We also have an English-speaking club, e-sports gaming nights, tech discussions, networking parties, and board game sessions.   

5. How does ASSIST Software give back to the community?

Volunteering and charity are essential to us, which is why we founded the ASSIST Humanitarian Foundation. We genuinely care about our community and want to improve the future. We invest in IT equipment for schools and award excellent teachers. We also help hospitals and fire departments enter the 21st century.   

We sponsor cultural events and deliver humanitarian aid to those in need. If you agree with our views, you can also donate.   

ASSIST Software Team Members