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.
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.
The React community recommends Jest as the React testing framework of choice.
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.
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.
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)
})
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With