Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test useRef with Jest and react-testing-library?

I'm using create-react-app, Jest and react-testing-library for the configuration of the chatbot project.

I have a functional component that uses useRef hook. When a new message comes useEffect hook is triggered and cause scrolling event by looking a ref's current property.

const ChatBot = () => {
  const chatBotMessagesRef = useRef(null)
  const chatBotContext = useContext(ChatBotContext)
  const { chat, typing } = chatBotContext

  useEffect(() => {
    if (typeof chatMessagesRef.current.scrollTo !== 'undefined' && chat && chat.length > 0) { 
       chatBotMessagesRef.current.scrollTo({
         top: chatMessagesRef.current.scrollHeight,
         behavior: 'smooth'
       })
    }
    // eslint-disable-next-line
  }, [chat, typing])

   return (
    <>
      <ChatBotHeader />
      <div className='chatbot' ref={chatBotMessagesRef}>
        {chat && chat.map((message, index) => {
          return <ChatBotBoard answers={message.answers} key={index} currentIndex={index + 1} />
        })}
        {typing &&
        <ServerMessage message='' typing isLiveChat={false} />
        }
      </div>
    </>
  )
}

I want to be able to test whether is scrollTo function triggered when a new chat item or typing comes, do you have any ideas? I couldn't find a way to test useRef.

like image 225
onuriltan Avatar asked Nov 27 '19 08:11

onuriltan


People also ask

How do you mock useRef in Jest react testing library?

To mock React useRef or a function inside a functional component with enzyme and Jest, we can mock the react module by mocking the useRef hook and getting the rest of the mocked module from the real module. import React, { useRef } from "react"; import { shallow } from "enzyme"; import Child2 from "./"; jest.

Should I use Jest or react testing library?

The React community recommends Jest as the React testing framework of choice.

How do you define useRef in react?

The useRef Hook allows you to persist values between renders. It can be used to store a mutable value that does not cause a re-render when updated. It can be used to access a DOM element directly.

How do you use useRef in react for input?

To make it work you'll need to create a reference to the input, assign the reference to ref attribute of the tag, and after mounting call the special method element. focus() on the element. Try the demo. const inputRef = useRef() creates a reference to hold the input element.


1 Answers

You can move your useEffect out of your component and pass a ref as a parameter to it. Something like

const useScrollTo = (chatMessagesRef, chat) => {
    useEffect(() => {
    if (typeof chatMessagesRef.current.scrollTo !== 'undefined' && chat && chat.length > 0) { 
       chatBotMessagesRef.current.scrollTo({
         top: chatMessagesRef.current.scrollHeight,
         behavior: 'smooth'
       })
    }
  }, [chat])
}

Now in your component

import useScrollTo from '../..'; // whatever is your path

const MyComponent = () => {
  const chatBotMessagesRef = useRef(null);
  const { chat } = useContext(ChatBotContext);

  useScrollTo(chatBotMessagesRef, chat);

  // your render..
}

Your useScrollTo test:

import useScrollTo from '../..'; // whatever is your path
import { renderHook } from '@testing-library/react-hooks'

it('should scroll', () => {
  const ref = {
    current: {
      scrollTo: jest.fn()
    }
  }
  const chat = ['message1', 'message2']

  renderHook(() => useScrollTo(ref, chat)) 

  expect(ref.current.scrollTo).toHaveBeenCalledTimes(1)
})
like image 123
Aritra Ghosh Avatar answered Oct 06 '22 08:10

Aritra Ghosh