0

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

1 Answer 1

1

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;
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.