Reputation: 2281
I'm using react-testing-library for test my component using custom hook. But I can't make it pass. Here is my code
function useInput<T>(): Return<T> {
const [input, setInput] = useState<T>({} as T);
const [isDirty, setDirty] = useState({} as Record<keyof T, boolean>);
const handleInputChange = (e: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
setInput({
...input,
[e.target.name]: e.target.value
});
setDirty({
...isDirty,
[e.target.name]: true
});
};
const resetInput = () => {
Object.keys(input).map((v) => (input[v as keyof T] as unknown as string) = '');
Object.keys(isDirty).map((v) => (isDirty[v as keyof T] as unknown as string) = '');
setInput({...input});
setDirty({...isDirty});
};
return [input, handleInputChange, isDirty, resetInput, setInput]
}
const Login: React.FC = () => {
const [input, handleChangeInput, isDirty, resetInput] = useInput<IInput>();
return (
<input
value={input.username}
onChange={handleChangeInput}
name={'username'}
className={classNames(`shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 mb-3 leading-tight focus:outline-none focus:shadow-outline`)}
id={'username'} type={'text'} placeholder={'Username'}/>
)
}
test
import React from "react";
import {render, unmountComponentAtNode} from "react-dom";
import Login from './index'
import {renderHook, act as actHook} from '@testing-library/react-hooks'
import {MemoryRouter} from "react-router-dom";
import {useInput} from '../hooks';
import { fireEvent } from '@testing-library/react';
describe('test login', () => {
it('to match snapshot', () => {
render(
<MemoryRouter>
<Login/>
</MemoryRouter>
,
container);
expect(container).toMatchSnapshot()
});
it('input correct when change username', () => { //can't pass
render(
<MemoryRouter>
<Login/>
</MemoryRouter>
,
container);
const {result} = renderHook(() => useInput());
const [input, handleChangeInput] = result.current;
const inputName = container.querySelector('#username');
fireEvent.change(inputName, {target: {value: 'test'}});
actHook(() => {
handleChangeInput({target: {name: 'username', value: 'test'}});
});
expect(input).toBe({
username: 'test'
})
})
});
My script test is. When input fireEvent call, input change value and value in hook useInput have same value. But I can make it pass. Where is my wrong? Please help
Upvotes: 0
Views: 864
Reputation: 758
React hooks testing library was created to test hooks without having to mount it on test component. You have to decide to either test the hook itself (without use of your Login component) or your component as whole - then you don't need hooks testing library at all - react-testing-library should be enough. Your fireEvent actually "fire" your hook without the part below
const {result} = renderHook(() => useInput());
const [input, handleChangeInput] = result.current;
Upvotes: 1