101

I am new to react-testing-library / jest and attempting to write a test to see if the navigation of routes (using react-router-dom) is performed correctly. So far I have been following the README and this tutorial on how to use.

One of my components uses scrollIntoView in a local function and this causes the test to fail.

TypeError: this.messagesEnd.scrollIntoView is not a function

  45 |
  46 |     scrollToBottom = () => {
> 47 |         this.messagesEnd.scrollIntoView({ behavior: "smooth" });
     |                          ^
  48 |     }
  49 |
  50 | 

This is the function in my chatbot component:

componentDidUpdate() {
    this.scrollToBottom();
}

scrollToBottom = () => {
    this.messagesEnd.scrollIntoView({ behavior: "smooth" });
}

And this is a sample of the tests that fail:

test('<App> default screen', () => {

    const { getByTestId, getByText } = renderWithRouter(<App />)

    expect(getByTestId('index'))

    const leftClick = {button: 0}
    fireEvent.click(getByText('View Chatbot'), leftClick) <-- test fails

    expect(getByTestId('chatbot'))

})

I have tried to use a mock function, however the error still remains.

This is where this.messageEnd is assigned:

    <div className="chatbot">
        <div className="chatbot-messages">
            //render messages here
        </div>
        <div className="chatbot-actions" ref={(el) => { this.messagesEnd = el; }}>
            //inputs for message actions here
        </div>
    </div>

I referenced code from this stack overflow question: How to scroll to bottom in react?

SOLUTION

test('<App> default screen', () => {

    window.HTMLElement.prototype.scrollIntoView = function() {};

    const { getByTestId, getByText } = renderWithRouter(<App />)

    expect(getByTestId('index'))

    const leftClick = {button: 0}
    fireEvent.click(getByText('View Chatbot'), leftClick)

    expect(getByTestId('chatbot'))

})
3
  • Can you post where you assign the value of this.messagesEnd? Commented Nov 13, 2018 at 7:43
  • Sure thing, I updated the original question. Commented Nov 13, 2018 at 21:27
  • Would it work if you force the casting? (<HTMLElement>this.messagesEnd).scrollIntoView({ behavior: "smooth" }); Commented Nov 14, 2018 at 0:28

2 Answers 2

135

scrollIntoView is not implemented in jsdom. Here's the issue: link.

You might get it working by manually adding it:

window.HTMLElement.prototype.scrollIntoView = function() {};
Sign up to request clarification or add additional context in comments.

3 Comments

Thank you @Gpx, this worked. I have added the solution to the original post.
can you please add bit of context, where should I place this line in React?
It depends on how your testing environment is set up. In Jest, you can have setup files: jestjs.io/docs/configuration#setupfiles-array
92

If we want to unit test 'scrollIntoView' function in a react application using react testing library then we can mock the function using 'jest'.

window.HTMLElement.prototype.scrollIntoView = jest.fn()

6 Comments

It's like we are mocking scrollIntoView function.
@Kriti. Please explain how this code helps the OP solve their issue in the answer itself. Please read this article to get a better understanding of what an answer is. Please also go through the site tour
just an observation, correct would be to use without immediate invocation. So, instead of jest.fn (), use jest.fn without parentheses.
Calling jest.fn() is correct here. Calling jest.fn() returns a mocked function that is then assigned. Then every time scrollIntoView is called, it will be calling the mocked function. From a technical standpoint, just assigning jest.fn would still work, but every time scrollIntoView was called it would actually be generating a new mock function and throwing the mocked function away. While this works for the OPs problem, it's not the correct way to do it.
Problem with mocking scrollIntoView is that, although we can make the mock function to call another function, we can never be sure that the scrolling will trigger that other function in a real case. Let's take an infinite scroll, I can still pass the test and my InfiniteScroller component does not trigger a load more in real case.
@Lee, you are correct.

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.