0

I'm trying to mock window.location in my tests. I have a file that exports certain configs based on window.location so I need to test if it is returning the correct configs based on the window location. I was first trying to set a testURL in jest config but from what I can see online, that this is not supported in create-react-app. So then I tried to go this route of mocking window location.

import config from 'src/config';
// this just returns an object with configs

delete global.window.location;
global.window.location = {
  ancestorOrigins: null,
  hash: null,
  host: 'test-app.com',
  port: '80',
  protocol: 'http',
  hostname: 'test-app.com',
  href: 'http://test-app.com',
  origin: 'http://test-app.com',
  pathname: null,
  search: null,
  assign: null,
  reload: null,
  replace: null
}

console.log(window.location) //logs the above so I can see it changes

describe('Configuration', () => {
  it('Loads correct config', () => {
    expect(config.serviceEnv.toEqual({...}));
    // if I add a console.log here it keeps returning the values relative to localhost, 
    // meaning it does not change. Also, if I add a console log to the config file it does not 
    // log the mock location
  })
})

Config.js

    const { hostname } = window.location;
    // adding a console log here keeps showing me default values instead of 
    // mock location and so in the test when I assert on the value returned 
    // it fails
    let serviceEnv;
    if (hostname.indexOf('dev') > -1) {
      serviceEnv = 'dev'
    } else if (hostname.indexOf('qa') > -1) 
        serviceEnv = 'qa'
    } else {
      serviceEnv = 'dev'
    } 
  }
}
export default {
  ..someotherConfigs,
  serviceEnv
}

Any ideas how can I test this? Appreciate any guidance, thanks!

Revision 1: Based on the post shared by Xiduzo in the comments I have changed the test to the following but still the location inside config file does not use the mocked location

describe('Configuration', () => {
  let windowSpy;
  beforeEach(() => {
      windowSpy = jest.spyOn(window, 'window', 'get')
  })

 afterEach(() => {
     windowSpy.mockRestore();  
 })

it('Loads correct config', () => {
    windowSpy.mockImplementation(() => ({
      location: {
        ancestorOrigins: null,
        hash: null,
        host: 'dummy.com',
        port: '80',
        protocol: 'http',
        hostname: 'test-app.com',
        href: 'http://test-app.com',
        origin: 'http://test-app.com',
        pathname: null,
        search: null,
        assign: null,
        reload: null,
        replace: null
      }
    })
    console.log(config)
    // still shows default config from else condition meaning it does not use the mock location data
  })
})
sayayin
  • 971
  • 5
  • 23
  • 36
  • Have you tried configuring jest using https://jestjs.io/docs/configuration#testenvironmentoptions-object ? – Xiduzo Oct 17 '22 at 20:50
  • No I have not, looking into it now. Thank you. I feel even if I find a way to change the default test url, my problem with mocking will still be there. – sayayin Oct 17 '22 at 21:07
  • You might also find some helpful information at: https://stackoverflow.com/questions/41885841/how-can-i-mock-the-javascript-window-object-using-jest – Xiduzo Oct 17 '22 at 21:15
  • 1
    I was just looking into implementing spy for the location. Thank you so much for sharing. I'll let you know how it works out. – sayayin Oct 17 '22 at 21:22
  • So implemented a spy and wrote a test to check for window undefined just like on that page. But not sure why the window.location from the other file still does not change. I'm going to post that file above too, so you can see what is in there. It is as simple as reading the location and return config based on that – sayayin Oct 17 '22 at 21:38
  • ok I posted above the file, not sure why that window.location is not changing – sayayin Oct 17 '22 at 21:44
  • I wrote once an article about it - maybe it will help: https://marek-rozmus.medium.com/mocking-window-object-d316050ae7a5 Try to use the `Object.defineProperty(window, 'location'` instead of assignment. – Marek Rozmus Oct 17 '22 at 22:03
  • Thanks for sharing but at this point don't think Im having issue with mocking location. Problem is that why the location inside config file does not use mocked location. – sayayin Oct 18 '22 at 01:30
  • @MarekRozmus so followed this post https://stackoverflow.com/questions/62265507/jest-mock-window-object-before-importing-a-dependency and used require to include the dependency and finally got it working so guess it was a ES6 import hoisting issue. This should be fine but not sure how I would mock the implementation for other cases. If I move the mockImplemenation method inside the test, I go back to the old issue. ohhh well Ideally wanted to test all cases. – sayayin Oct 18 '22 at 03:03
  • how does you `config.js` looks like? I mean you are calling it like this `config.baseConfig` and the part of code you've added looks like part of some function. – Marek Rozmus Oct 18 '22 at 08:18
  • That's because I am exporting at it as export default { ..., serviceEnv } but I did rename and move around somethings so that baseConfig should be serviceEnv (I'll update above). After using require and solving the main issue, I think the main issue was hoisting. And it does make sense because if config.js was getting hoisted that explains why that window.location was not changing – sayayin Oct 18 '22 at 14:11

0 Answers0