Codementor Events

Testing Material UI Forms with React-Testing-Library

Published May 04, 2021Last updated Oct 30, 2021
Testing Material UI Forms with React-Testing-Library

Test cases can be difficult to write when dealing with forms. I have found this especially difficult with my preferred UI library: Material UI. I love the components, design, and its seamless use with React, but when it comes to testing it can be difficult.

Below I'm going to show an example of an account delete request form I recently built and how I wrote my test cases.

I use jest + react-testing-library in my testing stack.

First, the form
The form itself was simple. A text field, checkbox, and submit button.
When the form loads the text field is empty and the checkbox is unchecked.
The submit button is disabled when the text field is empty or the checkbox is unchecked.

1_GzqB36N2faTP_iv874flXA.png

1_RKtKsiSMN8tO6T15nT-smA.png

My goal was to write tests for the different states the UI can be in

  1. password empty, checkbox unchecked, button disabled
  2. password filled, checkbox unchecked, button disabled
  3. password empty, checkbox checked, button disabled
  4. password filled, checkbox checked, button enabled

The code version of the form

example

A Few Things to Point Out

  • My TextFields have the data-testid set on the inputProps object, rather than the outer TextField. This will allow me to more easily manipulate the value of the TextField.

  • I'm importing the extended-expect dependency so I can use the toHaveClass check.

import "@testing-library/jest-dom/extend-expect"
expect(submit).toHaveClass("Mui-disabled");

I've found that class checks are the simplest way to test the state of some Material UI elements.

Below is the full test suite for the form. I'll spend the rest of the article going over each it block.

example

Default view
I like to include tests that make sure everything is as I expect it to be once the component is first rendered.

example

Password Only
Next, I make sure the button is disabled when only the password field has a value.

example

Confirm Only
Now, I do the same for an empty password and a checked checkbox

example

Enabled Submit
Finally, I check that the button is enabled when both the password and the checkbox are filled in.

example

Once all my tests are passing, I'm good to move onto the next feature.

Screen Shot 2021-05-04 at 12.00.25 PM.png

Discover and read more posts from Jesse Langford
get started
post commentsBe the first to share your opinion
Abhishek
4 months ago

When testing Material-UI forms with React-Testing-Library, focus on user interactions and expected outcomes. Use RTL’s utilities like fireEvent to simulate user input and assert that the form responds correctly. Leverage RTL queries to locate form elements and validate their states. Ensure comprehensive coverage by testing various scenarios, including edge cases and form validations. Mock API calls or utilize testing libraries like msw for server responses. By prioritizing user-centric testing, you can validate the form’s functionality, improve user experience, and maintain the reliability of Material-UI components in React applications.

To know more, read here: https://purecode.ai/blogs/mui-checkbox/

Gustavo Luchi
2 years ago

Hi Jesse, nice post. I was wondering if its good practice to test something that is associated with this specific implementation. If you or your organization is refactoring all components to Tailwind, for example, all tests would brake. In the other hand, for instance, if you tested expect(submit).toBeDisabled(), you would be unaware of implementation details (more about it on https://kentcdodds.com/blog/testing-implementation-details).

Jesse Langford
2 years ago

Hi Gustavo, good question. I’m ok with testing this way for Material UI. It’s unlike other UI libraries like Bootstrap or Semantic in that styling is done entirely by theme configuration and JSS. I can’t see any scenario where I would mix Material UI with something like Tailwind. Styling is tightly coupled with the library. If I was going to use another framework for styling I would probably switch component libraries.

m o
2 years ago

Even if you stick with Material UI, what if they rename that “Mui-disabled” class name to “Mui-is-disabled”? While this isn’t likely, it is entirely possible.

The point is to not focus on implementation details. Meaning because your test cases rely on implementation details (the implementation of a class name), and if the implementation of that class name changes, all of your tests break. Whereas if you are testing actual functionality, you can have any class name you wish and your tests will still be fine.

Focusing on why Material UI is unlike any other libraries tells me you are still focusing on the implementation details.

Show more replies