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.
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:
window.scrollTo = jest.fn()
describe("...", () => {
afterEach(() => {
jest.resetAllMocks()
})
afterAll(() => {
jest.clearAllMocks()
})
// Write your 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
:
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
:
module.exports = {
setupFilesAfterEnv: ["<rootDir>/test/setup/test-setup.js"],
}
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!