admin管理员组文章数量:1332345
So I'm trying to test a form input. First the form should display an error and then after a value is entered the user clicks a button and the error should be removed.
I think I understand why this is happening but I can't figure out how to test this feature.
I'm conditionally rendering the error message and updating the state so I know that is probably why it's telling me to wrap my test in act()
. I'm also telling the mock server to send an error state and I figured maybe since I overrode the initial handler that it would only respond with the error state that I defined. That's not working either.
I'm not sure how exactly to test this since I'm new to testing. I really appreciate any help.
Here is the test function:
it('clears validation error after username field is updated', async () => {
let validationError;
server.use(generateValidationError('username', 'Username cannot be null'));
setup();
await act(async () => {
userEvent.click(button);
validationError = await screen.findByText('Username cannot be null');
userEvent.type(usernameInput, 'username001');
userEvent.click(button);
expect(validationError).not.toBeInTheDocument();
});
});
So I'm trying to test a form input. First the form should display an error and then after a value is entered the user clicks a button and the error should be removed.
I think I understand why this is happening but I can't figure out how to test this feature.
I'm conditionally rendering the error message and updating the state so I know that is probably why it's telling me to wrap my test in act()
. I'm also telling the mock server to send an error state and I figured maybe since I overrode the initial handler that it would only respond with the error state that I defined. That's not working either.
I'm not sure how exactly to test this since I'm new to testing. I really appreciate any help.
Here is the test function:
it('clears validation error after username field is updated', async () => {
let validationError;
server.use(generateValidationError('username', 'Username cannot be null'));
setup();
await act(async () => {
userEvent.click(button);
validationError = await screen.findByText('Username cannot be null');
userEvent.type(usernameInput, 'username001');
userEvent.click(button);
expect(validationError).not.toBeInTheDocument();
});
});
Share
Improve this question
edited Nov 21, 2021 at 23:03
Journey_Man
asked Nov 21, 2021 at 22:27
Journey_ManJourney_Man
3211 gold badge2 silver badges16 bronze badges
3 Answers
Reset to default 2Since setting state in ponent or doing something asynchronously can take "some time" you should treat your situation as a potential promise-like situation.
To be sure your test always waits for any change that is happening, you can use waitFor
method and add callback function with your code to check some state. This is from React Testing library
it('clears validation error after username field is updated', async () => {
let validationError;
server.use(generateValidationError('username', 'Username cannot be null'));
setup();
await act(async () => {
userEvent.click(button);
userEvent.type(usernameInput, 'username001');
userEvent.click(button);
await waitFor(async () => {
validationError = await screen.findByText('Username cannot be null');
expect(validationError).not.toBeInTheDocument();
});
});
});
TIP
When you are asserting something that includes DOM element, always select that element after you do some action (change validation state in your case after button click).
In the code above I change position of that selector regarding the above tip.
In terms of approach, I would:
- Test the error is initially visible
- Click the button
- Test the error has disappeared
If you're going to use act()
, typically you place the assertions outside of its function body, see https://reactjs/docs/testing-recipes.html#act.
I'm not even sure you need act()
. The examples on the official testing-library docs seem to fulfil your needs:
- https://testing-library./docs/dom-testing-library/api-async#findby-queries
- https://testing-library./docs/react-testing-library/example-intro
It was really silly mistake. The first error I was getting was because I was hiding my form after a successful submission. So the ponent would unmount and then I wouldn't be able to test it. I figured out a work around by testing each field separately and making sure it doesn't successfully submit the form.
By fixing the above mistake I didn't need to use act() anymore as I wasn't getting any errors in jest. Tests successfully passed afterwards.
it.each`
field | message | label
${'username'} | ${'Username cannot be null'} | ${'Username'}
${'email'} | ${'Email cannot be null'} | ${'Email'}
${'password'} | ${'Password cannot be null'} | ${'Password'}
`(
'clears validation error after $field field is updated',
async ({ field, message, label }) => {
server.use(generateValidationError(field, message));
setup();
userEvent.click(button);
const validationError = await screen.findByText(message);
const inputByLabel = screen.getByLabelText(label);
userEvent.type(
inputByLabel,
label === 'Email' ? '[email protected]' : 'username001'
);
//this line was needed to stop the form from submitting
userEvent.type(confirmPasswordInput, 'newpassword');
userEvent.click(button);
await waitFor(() => {
expect(validationError).not.toBeInTheDocument();
});
}
);
本文标签:
版权声明:本文标题:javascript - Jest can't perform a React state update on an unmounted component + react state updates should be wrapped i 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1742324829a2453515.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论