Reputation: 480
I have a problem here that's stumping me, and I don't know how to go about fixing this. I have a very simple React Hooks functional component that uses the useState
hook, but I am having an issue with writing a test case for it (in Jest), with @testing-library/react
.
Here is the meat of the component:
// MyComponent.jsx
import InputComponent from '/some/folder/InputComponent';
...
export function MyComponent() {
const [randomStateVariable, setRandomStateVariable] = useState('');
...
const handleChange = value => setRandomStateVariable(value);
...
return (
<InputComponent
handleChange={handleChange}
input={{
value: randomStateVariable || ''
}}
/>
);
}
And then for my unit test file, I am doing the following:
// MyComponent.test.js
import renderer from 'react-test-renderer';
import { render } from '@testing-library/react';
...
import MyComponent from 'MyComponent';
...
it('runs handleChange', () => {
const props = {
actions: {
someAction: jest.fn()
},
input: 'some input value'
};
...
const component = renderer.create(<MyComponent {...props} />);
const inputSelect = component.root.findByType(InputComponent).props;
inputSelect.handleChange(props.input);
expect(props.actions.someAction).toHaveBeenCalledWith(props.input);
});
Now, the tests are all passing (I am using @testing-library/react
in other test cases in the file), but I am getting the following error when running the test suite:
When testing, code that causes React state updates should be wrapped into act(...):
I am not sure how to go about correcting this. I don't have the @testing-library/react-hooks
package installed, and I am unsure of where I should be importing act
from. Should I be using the react-test-renderer
for this, and import act
from that package, or should I be importing it from @testing-library/react
?
I don't know how to write a test case, or modify the existing test case, in using act
, to get rid of the console error. Is there anyone that can assist, or point me in the right direction for something like this?
Thank you very much!
Upvotes: 0
Views: 3988
Reputation: 102207
TestRenderer.act() is same with act() of react-dom/test-utils
module. So you just need to import it from react-test-renderer
package. @testing-library/react
is another react test library, you only need to choose one of the two. It will be confusing to use together, because each test library has its test method and process, which may not be compatible.
act()
:
When writing UI tests, tasks like rendering, user events, or data fetching can be considered as “units” of interaction with a user interface.
react-dom/test-utils
provides a helper calledact()
that makes sure all updates related to these “units” have been processed and applied to the DOM before you make any assertions:
inputSelect.handleChange(props.input)
trigger an updated operation, it should be put in act()
.
E.g.
MyComponent.test.tsx
:
import React, { useState } from 'react';
import InputComponent from './InputComponent';
export function MyComponent({ actions, input }) {
const [randomStateVariable, setRandomStateVariable] = useState('');
const handleChange = (value) => setRandomStateVariable(value);
return (
<InputComponent
handleChange={handleChange}
input={{
value: randomStateVariable || '',
}}
/>
);
}
MyComponent.test.tsx
:
import React from 'react';
import renderer, { act } from 'react-test-renderer';
import { MyComponent } from './MyComponent';
import InputComponent from './InputComponent';
describe('65786455', () => {
it('runs handleChange', () => {
const props = {
actions: {
someAction: jest.fn(),
},
input: 'some input value',
};
const component = renderer.create(<MyComponent {...props} />);
const inputSelect = component.root.findByType(InputComponent).props;
expect(inputSelect.input.value).toBe('');
act(() => {
inputSelect.handleChange(props.input);
});
expect(component.root.findByType(InputComponent).props.input.value).toBe('some input value');
});
});
unit test result:
PASS examples/65786455/MyComponent.test.tsx
65786455
✓ runs handleChange (24 ms)
--------------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
--------------------|---------|----------|---------|---------|-------------------
All files | 100 | 100 | 100 | 100 |
InputComponent.tsx | 100 | 100 | 100 | 100 |
MyComponent.tsx | 100 | 100 | 100 | 100 |
--------------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 5.878 s
Upvotes: 3