How to spyOn window.location.assign on Vuejs Application with Jest?

Viewed 2590

I am needing to spyOn window.location.assign for my unit test. But when I run the test I get this error.

Cannot spy the assign property because it is not a function; undefined given instead

Here is my code:

jest.spyOn(window.location, "assign");

Could anyone give me some hints or solutions on this case?

2 Answers

Since Jest v25 (Which uses a newer version of JSDOM) you will get the following error:

TypeError: Cannot assign to read only property 'assign' of object '[object Location]'

This is not a Jest/JSDOM bug by the way. This is normal browser behaviour and JSDOM tries to act like a real browser.

A workaround is to remove the location object, create your own one and after running your tests you should reset it to the original location object:

describe('My awesome unit test', () => {
  // we need to save the original object for later to not affect tests from other files
  const realLocation = global.location

  beforeAll(() => {
    delete global.location
    global.location = { assign: jest.fn() }
    // or even like this if you are also using other location properties (or if TypeScript complains):
    // global.location = { ...realLocation, assign: jest.fn() }
  })

  afterAll(() => {
    global.location = realLocation
  })

  it('should call location.assign', () => {    
    // ...your test code

    expect(global.location.assign).toHaveBeenCalled()

    // or even better:
    // expect(global.location.assign).toHaveBeenCalledWith('/my_link')
  })
})

As window can only be accessed through the global keyword in jest tests and window.location.assign is not implemented in jsdom, you can try

jest
 .spyOn(global.location, "assign")
 .mockImplementation(url => console.log(url))
Related