Reputation: 65
I'm new to React and trying to test my codes using jest & testing-library/react.
I've made a simple select box and fired the change event on the box. All I wanted is just getting the state but I still don't know how to get it.
This is my component :
import React from "react";
import ReactDOM, { render } from "react-dom";
import NativeSelect from "@material-ui/core/NativeSelect";
const MyTest = () => {
const [option, setOption] = React.useState("1");
const handleChange = React.useCallback(e => {
setOption(e.target.value);
}, []);
return (
<div>
<h3>selected : {option}</h3>
<NativeSelect
inputProps={{ "data-testid": "test-input" }}
value={option}
onChange={handleChange}
>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</NativeSelect>
</div>
);
};
export default MyTest;
This is the test :
import React from "react";
import { renderHook, act } from "@testing-library/react-hooks";
import { render, fireEvent } from "@testing-library/react";
import MyTest from "./MyTest";
test("should change state", () => {
const { result } = renderHook(() => MyTest());
let { getByTestId } = render(<MyTest />);
const selectNode = getByTestId("test-input");
expect(selectNode).not.toBeNull();
act(() => {
fireEvent.change(selectNode, { target: { value: "2" } });
});
expect(result.current.option).toBe("2");
});
codesandbox is here : https://codesandbox.io/s/distracted-wave-j5fed?fontsize=14
Then the error message from the test is : "Comparing two different types of values. Expected string but received undefined."
I guess "result.current.option" is the wrong way to get the state... How can I get the state of the component?
Plus, according to what I've searched, props and states can be tested quite easily with Enzyme.
If this is right, should I use Enzyme instead of react-testing-library to test states?
Thanks so much in advance.
Upvotes: 1
Views: 15656
Reputation:
These two are different objects:
const { result } = renderHook(() => MyTest());
let { getByTestId } = render(<MyTest />);
result.current.option is undefined because result is a component returned not a hook function.
Either you test the state or you test the rendered component.
For testing component:
In your test it should be: expect(selectNode.value).toBe("2")
or you follow this from docs: https://reactjs.org/docs/hooks-faq.html#how-to-test-components-that-use-hooks
For testing the state of your hooks. You should extract a custom hook and test it like this.
From https://github.com/testing-library/react-hooks-testing-library:
function useCounter() {
const [count, setCount] = useState(0)
const increment = useCallback(() => setCount((x) => x + 1), [])
return { count, increment }
}
test('should increment counter', () => {
const { result } = renderHook(() => useCounter())
act(() => {
result.current.increment()
})
expect(result.current.count).toBe(1)
})
Upvotes: 3