I am trying to mock the window.navigator.language
attribute in the browser in my jest unit tests so I can test that the content on my page is using the correct language
I have found people online using this:
Object.defineProperty(window.navigator, 'language', {value: 'es', configurable: true});
I have set it right at the top of my test file and it is working there
however, when I redefine in an individual test (and people set to make sure configurable was set to true) it wont redefine it and is just using the old value, does anyone know a way to definitely change it?
beforeEach(() => { jest.clearAllMocks() Object.defineProperty(global.navigator, 'language', {value: 'es', configurable: true}); wrapper = shallow(<Component {...props} />) }) it('should do thing 1', () => { Object.defineProperty(window.navigator, 'language', {value: 'de', configurable: true}); expect(wrapper.state('currentLanguage')).toEqual('de') }) it('should do thing 2', () => { Object.defineProperty(window.navigator, 'language', {value: 'pt', configurable: true}); expect(wrapper.state('currentLanguage')).toEqual('pt') })
for these tests it is not changing the language to the new language I have set, always using the one at the top
Jest's spyOn method is used to spy on a method call on an object. It is also very beneficial in cases where the Jest mock module or mock function might not be the best tool for the job on hand. While writing unit tests you only test one particular unit of code, generally a function.
To mock any file first step is to tell Jest that you are planning to mock it. After telling Jest that you will be mocking the particular file, you need to tell Jest what it should do, instead of executing the function. You can increase a counter or return a particular value to know that the function was called.
window.navigator
and its properties are read-only, this is the reason why Object.defineProperty
is needed to set window.navigator.language
. It's supposed to work for changing property value multiple times.
The problem is that the component is already instantiated in beforeEach
, window.navigator.language
changes don't affect it.
Using Object.defineProperty
for mocking properties manually will require to store original descriptor and restore it manually as well. This can be done with jest.spyOn
. jest.clearAllMocks()
wouldn't help for manual spies/mocks, it may be unneeded for Jest spies.
It likely should be:
let languageGetter; beforeEach(() => { languageGetter = jest.spyOn(window.navigator, 'language', 'get') }) it('should do thing 1', () => { languageGetter.mockReturnValue('de') wrapper = shallow(<Component {...props} />) expect(wrapper.state('currentLanguage')).toEqual('de') }) ...
Alternatively
jest config file
setupFiles: ['./test/mock-data/globals.js']
globals.js
const navigator = { language: 'Chalcatongo Mixtec', ...anyOtherPropertiesYouNeed }; Object.defineProperty(window, 'navigator', { value: navigator, writable: true });
then you can mutate freely in your individual test setup
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