How are we meant to test controlled components?
See original GitHub issue"@testing-library/user-event": "^12.1.10", (From CRA) - "version": "12.6.0" in node modules.
-
Testing Framework and version:
-
DOM Environment:
Jest.
I’ve copied the code from this closed issue: https://github.com/testing-library/user-event/issues/307
import React from "react";
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
test("THE BUGGED TEST", async () => {
let formValue = "";
const setFormValue = jest.fn((newFormValue) => {
formValue = newFormValue;
});
render(
<input
data-testid="thisinput"
type="text"
value={formValue}
onChange={(event) => setFormValue(event.target.value)}
/>
);
await userEvent.type(screen.getByTestId("thisinput"), "Ben Mayer");
expect(setFormValue).toHaveBeenCalledWith("Ben Mayer");
expect(screen.getByTestId("thisinput")).toHaveDisplayValue("Ben Mayer");
});
The output I get is:
FAIL src/TestSandbox.test.tsx
✕ THE BUGGED TEST (55 ms)
● THE BUGGED TEST
expect(jest.fn()).toHaveBeenCalledWith(...expected)
Expected: "Ben Mayer"
Received
1: "B"
2: "e"
3: "n"
Number of calls: 9
20 | await userEvent.type(screen.getByTestId("thisinput"), "Ben Mayer");
21 |
> 22 | expect(setFormValue).toHaveBeenCalledWith("Ben Mayer");
| ^
23 |
24 | expect(screen.getByTestId("thisinput")).toHaveDisplayValue("Ben Mayer");
25 | });
at Object.<anonymous>.test (src/TestSandbox.test.tsx:22:24)
This makes sense to me as I can’t see that reassigning the ‘formValue’ variable will cause a rerender for RTL.
However, from reading the issue thread, it looks like Kent is saying that it should work?
I’ve searched ‘controlled components’ across the User Events github issues, and that’s the only issue for it.
How are we mean to test controlled components, like a simple text field like this? Can an example be added to the main readme?
Issue Analytics
- State:
- Created 3 years ago
- Reactions:3
- Comments:9 (4 by maintainers)
Top Results From Across the Web
4 methods for testing controlled React components - Moxio
One of the ways you can test complex behavior that includes state changes, is by manually telling the component to re-render, and what...
Read more >Controlled vs Uncontrolled Components in React - ITNEXT
In most cases, we recommend using controlled components to implement forms. In a controlled component, form data is handled by a React component....
Read more >Controlled vs. uncontrolled components in React
In this tutorial, we'll explain the difference between controlled and uncontrolled components in React with practical examples.
Read more >How to Test React Components: the Complete Guide
Controlled component Forms. A controlled component form essentially means the form will work through the React state instead of the form ...
Read more >How to properly test controlled input component which ...
I want to test controlled component using Jest/enzyme. ... Do you have an example of such test with react testing library.
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
Thanks for providing these informations. I understand your problem is more how to organize your tests than how to actually write them.
Some might stone me for this, but I feel like tests should reflect your codes objective and the risks to produce bugs instead of some philosophy. So for a lot of simple components this means that a strict “unit test” would basically just protect you from a typo by requiring you to type it twice (once in the component and once in the test). This sounds useless to me and is rendered even more useless by autocompletion and the like. The DRY devil has possessed me regarding code as well as in the test, so whenever an additional test requires more copy and paste than original typing there is probably a better way. That said, let’s head over to your scenarios:
Setup function to test similar components
You should use a setup function in your component tests that reflects the expected environment for your components like:
This tests your exported components against the behavior and with the requirements you laid out for the consumers of your library. It prevents you from repeating yourself in the tests and also makes the test much more readable.
Testing wiring of components
If your
DynamicForm
does some magic with the props you can test if you pass down the correct results at the correct spots by inspecting the rendered React tree with react-test-renderer.If you don’t do some magic, your tests will just be a repetition of
FormItemMapper
. (imho see above) You can however improve your confidence in passing down correct props at correct places by using TypeScript.Dependency Injection
If you manage state up the tree, you can make your state managing component more testable by making the used components injectable.
@ph-fritsche you might be misunderstanding what I mean by controlled component in this case What I mean is where ‘the value of the component is controlled by its parent.’
Eg.