Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Intercept navigation change with jest.js (or how to override and restore location.href)

Tags:

Application code is calling location.href = "some-url". I want to write a test that verify the navigation redirect has happened.

Using jest on jsdom, I tried to do it with overriding location.href setter using jest mock function and it is working.

But now I can't seems to restore the location.href property at the test cleanup, and it failing the rest of the tests which relay on 'location.href'.

it('test navigation happened', () => {   const originalLocationHref = Object.getOwnPropertyDescriptor(window.location, 'href'); // returns undefined    spyFn = jest.fn();   Object.defineProperty(window.location, 'href', {     set: spyFn,     enumerable: true,     configurable: true   });    someAppCodeThatShouldRedirectToSomeUrl();    expect(spyFn).toBeCalledWith('http://some-url'); // this is working    // Cleanup code, not working, because originalLocationHref is undefined   Object.defineProperty(window.location, 'href', originalLocationHref);   }); 

What am I missing? Why Object.getOwnPropertyDescriptor(window.location, 'href'); is undefined?

Is there a better way to intercept navigation events in order to test it?

Thanks

like image 948
avivr Avatar asked Sep 12 '17 06:09

avivr


2 Answers

Use location.assign() method instead instead of assigning new location string to location.href. Then you can mock and test it with no problems:

it('test navigation happened', () => {   window.location.assign = jest.fn();    // here you call location.assign('http://some-url');   redirectToSomeUrl();    expect(window.location.assign).toBeCalledWith('http://some-url');    // location.href hasn't changed because location.assign was mocked }); 
like image 187
quotesBro Avatar answered Oct 03 '22 22:10

quotesBro


Newer jest/jsdom versions do not allow to set window.location.assign anymore. It can be fixed like this:

delete window.location; window.location = { assign: jest.fn() }; 

Note that this removes all other objects from window.location, you might need to mock more of its objects depending on your test and application code.

Source: https://remarkablemark.org/blog/2018/11/17/mock-window-location/

like image 44
fabb Avatar answered Oct 03 '22 21:10

fabb