jest: debugging 'not implemented' errors

2021-09-13

 | 

~2 min read

 | 

336 words

I recently added a feature to an app that scrolls the user to the top of page on navigation.

Unfortunately, this started spewing errors in my tests!

console.error
      Error: Not implemented: window.scrollTo
          at module.exports...

       5 |   const { pathname } = useLocation();
       6 |   useEffect(() => {
    >  7 |     window.scrollTo(0, 0);
         |            ^
       8 |   }, [pathname]);
       9 |   return null;
      10 | }

      at VirtualConsole.<anonymous> (node_modules/jsdom/lib/jsdom/virtual-console.js:29:45)
      at module.exports (node_modules/jsdom/lib/jsdom/browser/not-implemented.js:12:26)
      at node_modules/jsdom/lib/jsdom/browser/Window.js:563:7
      at src/components/ScrollToTop/ScrollToTop.tsx:7:12
      at invokePassiveEffectCreate (node_modules/react-dom/cjs/react-dom.development.js:23487:20)
      at HTMLUnknownElement.callCallback (node_modules/react-dom/cjs/react-dom.development.js:3945:14)
      at innerInvokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:316:27)

While my tests weren’t failing - this noise was annoying.

Depending on the scope of the problem - there are a few different solutions.

Narrow Scope: Affects Only A Limited Number of Tests

If you have a limited number of tests that this affects, one of the simplest solutions is to mock the function at the top of a test file and then reset the mocks after the tests have run.

At the top of a test file, mock the function:

**/*.test.js
window.scrollTo = jest.fn()

describe("...", () => {
  afterEach(() => {
    jest.resetAllMocks()
  })
  afterAll(() => {
    jest.clearAllMocks()
  })
  // Write your tests...
})

Broad Scope: Affects Most Tests

What about situations where nearly every test is going to require this mock? It’d be awfully inconvenient to have to do this for every test file!

Fortunately, Jest is aware of situations like this and that’s why it has a setupFilesAfterEnv (which I wrote about previously in the context of extending assertion libraries). Here’s how it might look for our narrow case (though, I think the pattern’s illustrative).

Mock the scrollTo property on the window object with a noop:

./test/setup/test-setup.js
const noop = () => {}
Object.defineProperty(window, "scrollTo", { value: noop, writable: true })

Then, we make sure Jest is aware of it by modifying our jest.config.js:

./jest.config.js
module.exports = {
  setupFilesAfterEnv: ["<rootDir>/test/setup/test-setup.js"],
}

Conclusion

We have multiple approaches to solve the problem of missing functions. Hopefully one of these is appropriate for your situation!


Hi there and thanks for reading! My name's Stephen. I live in Chicago with my wife, Kate, and dog, Finn. Want more? See about and get in touch!