jsdom: Error: Not implemented: navigation
After recent upgrade jest
(which uses jsdom in background) from version 21.2.0 to 22.0.6 I have started getting error: "Error: Not implemented:" navigation
My code relies on window.location
and I use in tests:
beforeEach(() => {
window.location.href = `/ms/submission/?mybib`;
window.location.search = '?mybib';
});
Is there a way to define a value of window.location.search
using new version of jsdom?
About this issue
- Original URL
- State: open
- Created 6 years ago
- Reactions: 90
- Comments: 66 (6 by maintainers)
Allow me to post the answer to my own question š I simply replace the usages of
window.location = url;
andwindow.location.href = url;
withand then in my tests I did:
Works like a charm - hope it can be of help to someone else š
If you donāt want to change your code to use
location.assign
- this seems to work with JSDom 11 and 13 (though thereās a chance JSDom might break it in the futureā¦)I can see that there has been a lot of struggle with this from a lot of people.
In my case I had an issue while clicking on html anchor tag element in order to test that analytics are fired correctly. None of the above solutions worked.
In the end it was something very simpleā¦
Attaching a click event listener to the anchor tag before emitting the click event does the trick.
I hope this will help someone else facing the same issue.
The last answer worked for me, but I had to define
replace
:Hope it helps.
This is what worked for me:
jsdom does not support navigation, so setting window.location.href or similar will give this message. Iām not sure if Jest was just suppressing these messages before, or what.
This is probably something you should fix in your tests, because it means that if you were running those tests in the browser, the test runner would get completely blown away as you navigated the page to a new URL, and you would never see any tests results. In jsdom instead we just output a message to the console, which you can ignore if you want, or you can fix your tests to make them work better in more environments.
Anyway, Iād like to add more documentation on this for people, so Iāll leave this issue open to track doing so.
Is anyone else running into the same
Error: Not implemented: navigation (except hash changes)
during Jest tests that fire a click event on an anchor element with anhref
? For my tests, Iām spying on a function that gets calledonClick
and making assertions about that so I need to actually fire the click event on the anchor element.The solutions above related to mocking
window.location
work for me where I am explicitly callingwindow.location.replace
orwindow.location.assign
, but donāt help for this case where the navigation originates from an anchor element being clicked.Any ideas on solutions? Thanks!
Possible solution is to rely on dependency injection/mock for the
window
object in unit tests.Something like:
This is not ideal but as said by @domenic:
For now we live with this and yes we change our implementation code for tests which is considered bad practice but we also sleep well at night!
Happy testing
We used
pushState
to make this to work@zxiestās Jest version of @hontasā solution didnāt work for me, but this did:
@hontasās solution helped:
I did use
window.location.assign(Config.BASE_URL);
in my code.And hereās the test:
@Sabrinovsky No, I ended up just adding a script to the
setupFiles
in my jest config that would swallow the console errors coming from jsdom navigation so that they werenāt cluttering up our tests. More of a bandaid than anything else, but it sounded like these errors are to be expected in our test setup.Hereās the script that I run before my tests:
@nickhallph I replaced it to
window.location
as you wrote but result the sameTypeError: Cannot redefine property: assign
Any ideas?Based on answer from @chrisbateman I managed to get this working in a Jest environment. For anyone who is using Jest, here is my workaround:
This is a difficult situation. JSDOM does not fully supports navigation (other than breadcrumbs) and JSDOM does not allow us to mock-out navigation. The end result is that I canāt write tests which ultimately attempt to trigger navigation.
If JSDOM did learn to navigate (Iām not even sure what that means), maybe I could assert about being on the appropriate page. For my testing use cases, though, asserting the navigation was triggered, rather than actually performed, is much cleaner/faster. Itās what Iāve historically done when testing using jsdom and now itās broken.
If you get
TypeError: Cannot assign to read only property 'assign' of object '[object Location]'
, then using something like this in yourjest.setup.ts
:Same problem, Iām using
window.location.search = foo;
in my code and I would like to test it using jsdom (and jest) š¤PS: Related to https://github.com/facebook/jest/issues/5266
Well in this case it wouldnāt doing anything different, other than not unloading the current page context. Iād still expect
window.location.href
to be updated, etc.jsdom is not intended to provide a testing library. Weāre providing a browser implementation. If itās not suitable for your purposes, then you should not use it.
For anyone who is interested, hereās how I adapted the @markoboy solution in my Jest test with Vue3:
I am currently using Jest
26.0.1
and the below works for me:Use
window.location.assign(url)
to change the window location.Mock the location object as follows (note that not deleting and rebuilding the object first still results in the not implemented error in the noted version of Jest and earlier I think, also
Object.defineProperty
doesnāt work and still results in the error):It would be really nice if jest allowed us to easily mock location without all of these constant issues and changes. I was previously using just
window.location.assign = jest.fn()
without any problems for a long time, then I upgraded from v24 and now this.Agree this should work out of the box. We mock
window.location
at FB, but that conflicts with jsdomāsHistory
implementation.Is there any way to find out which test is triggering the āNot implemented: navigationā message? I have a suite of 43 tests - the error is being displayed only once and it keeps bouncing around. I canāt tell which test to fix!!! The stack trace gives me no indication of the culprit:
As a small team, we would certainly appreciate help from the larger projects that depend on us to properly implement navigation in jsdom.
If anyone is interested, https://github.com/jsdom/jsdom/pull/1913 could be a good place to start.
Is there a way to fail tests when
'Error: Not implemented: navigation (except hash changes)'
is thrown? Iām using vitest and couldnāt find any type of console message that would actually fail the tests (info, warning etc). Iām trying to do something liketo make sure that the navigation is happening or not happening. In my case itās important to make sure that the disabled link is not navigating anywhere on click
Whatās the workaround here if the navigation event is coming from a deeply nested click on an element wrapped in an
<a>
tag? Iām not able to easily stub the onClick handler to add ae.preventDefault()
and I didnāt see and easy way to intercept this error and know if it was an anchor click or location.assignIn all of your replies in this thread, you seem to be completely missing the fact that there are ways to test against the DOM and changes in the location, as is done when testing frameworks like React/Angular/Vue. We are able to fire events which manipulate the DOM, and this is pretty much whatās tested everywhere in these front-end frameworks. We arenāt testing inside of a browser; weāre testing using jest or other test frameworks; we just need to be able to actually stub out these for things like React to be rid of the
console.error
that is produced by JSDom.Perhaps you could help users here with some direction on doing this, rather than telling everybody to go fix their ābroken codeā that wasnāt even written by them. Nothing youāve said here has been helpful or even really factual at all.
Kinda blows my mind that this issue is still open without conclusion since Jan of 2018.
Frankly, this issue is about the console.error coming out of JSDom, and itās not about any sort of broken tests. The error just looks like itās something breaking, but itās just a console.error.
Thank you for this!
For anyone who wants to make TypeScript happy
This worked for me
The issue with examples is that methods and getters are not use. What I do is basically replace Location object by URL object. URL has all the properties of Location (search, host, hash, etc).
@chrisbateman @hamzahamidi thanks, that solutions worked well.
Maybe itās not a good practice, but we have some tests, those rely on location/host/hostname and other location properties. So mocking location as we want and restoring afterwards worked for me.
Totally get what youāre saying. The recent Jest 22 update went from JSDOM 9 to 11 IIRC, so the behavior back in 9.x might have been quite different.
All that aside, I would love to see navigation implemented in JSDOM with some sort of flag to make it a no-op in terms of loading a different page (in similar spirit to HTML5 pushstate.) The library is very commonly used for testing purposes so, while perhaps a quirky request, it would be used often.
In my situation project upgraded Jest from 23 to 26 version. I had a problem with
location.search
. Had the same errorError: Not implemented: navigation
. Module I tested gets values of search query params. Next implementation worked for me:This worked for me, thanks! However I had to use the
done
argument from jest test(), otherwise I wouldnāt be sure that the expect was evaluated and the test might had ended successfully anyway:Thanks mate, youāve saved me a day! š
Same problem as @yuri-sakharov running mocha.
By no means I seem able to replace/update/mock or do anything with
window.location.*
. The only way I see around this is creating my own customwindow.location
mock and change the entire codebase to depend on that.It seems that in some cases you just canāt get rid of this error. š¦
If you click on HyperlinkElement, you get to the
HTMLHyperlinkElementUtilsImpl
class, which at some point gets right into thenavigateFetch
function, which does nothing but throw an errorSo if you use a HyperlinkElement in a test, you are doomed to this error.
There could be two solutions:
and I use it as
act
method from react:If it helps anyone this is what I did. We are using mocha not jest so only have sinon available.
You can then freely stubā¦
const assignStub = sandbox.stub(window.location, 'assign');
This worked for me.
As I understand jest changed something in new version (ājestā: ā^26.0.1ā) so this works right now:
After updating to jsdom 12.2.0 got error: TypeError: Cannot redefine property: assign on
const assign = sinon.stub(document.location, 'assign')
how to fix it?