Reference to window specific properties when using Jest in React Native
I followed the docs and moved to the JS SDK for our react native app. We use jest for testing and it's throwing errors despite using the react-native preset.
● Test suite failed to run
ReferenceError: window is not defined
at node_modules/amplitude-js/amplitude.js:778:12
at node_modules/amplitude-js/amplitude.js:2:83
at Object.<anonymous> (node_modules/amplitude-js/amplitude.js:1:2)
at Object.<anonymous> (node_modules/core-mobile/src/services/tracking/index.js:6:1)
To solve this I added a window: {} global to my test environment but then it throws error for more window specific properties such as navigator
● Test suite failed to run
ReferenceError: navigator is not defined
at getLanguage (node_modules/amplitude-js/amplitude.js:3219:5)
at node_modules/amplitude-js/amplitude.js:3223:15
at node_modules/amplitude-js/amplitude.js:2:83
at Object.<anonymous> (node_modules/amplitude-js/amplitude.js:1:2)
at Object.<anonymous> (node_modules/core-mobile/src/services/tracking/index.js:6:1)
I'd to add the following to my jest config. Not sure if its the best way to resolve this issue:
"globals": {
"window": {},
"navigator": {}
}
Yeah. That's not ideal. Given that jest is the way to write tests for the platform, we'll look into make the experience a bit better here.
For anyone else struggling with this, I think the easiest way around it is to bypass jest's automocking and explicitly provide a module factory for amplitude. E.g. mocking the module like this:
import {getInstance} from 'amplitude-js';
jest.mock('amplitude-js', () => {
const instance = {
init: jest.fn(),
logEvent: jest.fn(),
setUserId: jest.fn(),
setUserProperties: jest.fn(),
// ...
};
return {
getInstance: () => instance,
};
});
Will provide the ability to make assertions like this:
const mockAmplitude = getInstance();
// ... do something ...
expect(mockAmplitude.logEvent).toHaveBeenCalled();
If it's affecting a lot of tests a manual mock might be better.