New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Error: Not implemented: navigation #2112
Comments
I'm getting this error too
|
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. |
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. |
I don't think we should add a flag that makes your tests run different in jsdom than in browsers. Then your stuff could be broken in browsers (e.g. it could be redirecting users to some other page, instead of doing the action that your tests see happening) and you wouldn't even notice! |
Well in this case it wouldn't doing anything different, other than not unloading the current page context. I'd still expect |
@domenic I'm having the same issue and I was wondering if there is some sort of best practice to setup JSDOM with an app that sets |
Allow me to post the answer to my own question 😁 window.location.assign(url); and then in my tests I did: sinon.stub(window.location, 'assign');
expect(window.location.assign).to.have.been.calledWith(url); Works like a charm - hope it can be of help to someone else 👍 |
Agree this should work out of the box. We mock |
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, #1913 could be a good place to start. |
Possible solution is to rely on dependency injection/mock for the Something like: it('can test', () => {
const mockWindow = {location: {href: null}};
fn({window: mockWindow});
expect(mockWindow.href).toEqual('something');
}); 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 |
@hontas's solution helped: I did use And here's the test:
|
Same problem, I'm using PS: Related to jestjs/jest#5266 |
After updating to jsdom 12.2.0 got error: |
needs to be:
you need to replace |
I have the following function export const isLocalHost = () => Boolean(
window.location.hostname === 'localhost' ||
// [::1] is the IPv6 localhost address.
window.location.hostname === '[::1]' ||
// 127.0.0.1/8 is considered localhost for IPv4.
window.location.hostname.match(
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
)
); for me to be able to test that it works I inject directly the it('#isLocalHost should return true for all the cases of localhost', () => {
window.location.hostname = 'localhost';
expect(isLocalHost()).toBeTruthy();
window.location.hostname = '[::1]';
expect(isLocalHost()).toBeTruthy();
window.location.hostname = '127.0.0.1';
expect(isLocalHost()).toBeTruthy();
// Reset back the hostname to avoid issues with it
window.location.hostname = '';
}); But I am getting this error. I don't expect I am confused on why I keep getting this error, I just want to be able to setup the value. |
@nickhallph |
Same problem as @yuri-sakharov running mocha. By no means I seem able to replace/update/mock or do anything with |
@zxiest's Jest version of @hontas' solution didn't work for me, but this did: window.location.assign = jest.fn();
expect(window.location.assign).toHaveBeenCalledWith('https://correct-uri.com');
window.location.assign.mockRestore(); |
If you don't want to change your code to use delete window.location;
window.location = {}; // or stub/spy etc. |
The last answer worked for me, but I had to define delete window.location
window.location = { replace: jest.fn() } Hope it helps. |
I'm getting TypeError: Cannot redefine property: assign with sinon 7.2.3 and jsdom 13.2.0. No idea why this works for some people and not others? |
This is what worked for me: global.window = Object.create(window);
const url = 'http://localhost';
Object.defineProperty(window, 'location', {
value: {
href: url,
},
writable: true,
}); |
We used window.history.pushState(
{},
'',
'http://localhost/something/123?order=asc'
); |
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 it helps anyone this is what I did. We are using mocha not jest so only have sinon available.
You can then freely stub... |
This worked for me with angular. Ty @Sabrinovsky |
Second attempt at this, my previous attempt broke using the This solves that issue...
You can then freely stub... |
Thank you for this! For anyone who wants to make TypeScript happy import { VirtualConsole } from 'jsdom';
declare global {
interface Window {
_virtualConsole: VirtualConsole;
}
} |
What's the workaround here if the navigation event is coming from a deeply nested click on an element wrapped in an |
Solves warnings about navigation not being implemented in JSDOM: jsdom/jsdom#2112
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... clickedLink = getAllByRole('link').find((link) =>
link.textContent?.includes(getDirectionsText),
);
clickedLink.addEventListener(
'click',
(event) => event.preventDefault(),
false,
);
userEvent.click(clickedLink); 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. |
For anyone who is interested, here's how I adapted the @markoboy solution in my Jest test with Vue3:
|
I think this is the issue I just ran into. The response below yours is what triggered a realization for me. I was testing this in the browser by setting a breakpoint on the However, I will say that I'm a bit confused why the test passes on its own without this kind of event listener, but needs the event listener when run in the same file as other tests. Probably something else I'm missing here that could make my test better... Anyway, here's what I tried. Again, this is for an anchor element with an window.addEventListener('beforeunload', function () {
// make your assertion here based on w/e it is your anchor's click handler does
});
// click your anchor after later in your test |
In 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 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. |
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. |
Makes much more sense. |
Hey guys! I found a solution without using mock or Object.defineProperty or by creating a. new window etc. ...
I think the reason for the error we all had is that there's something wrong going on with the browser history in test env (I'm personally using react-router v6 with ). Anyway, the code snippet above replaces the current URL with the one passed as the third argument of the .replaceState() function by manipulating not the URL directly, but the history of navigation. More about this function here: https://developer.mozilla.org/en-US/docs/Web/API/History/replaceState Hope it was helpful! 🔥 |
Is there a way to fail tests when
to 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 |
it("show a error message if the download fails", async () => {
....
const spyConsoleError = jest
.spyOn(console, "error")
.mockImplementation(() => {});
....
await waitFor(() => {
expect(spyConsoleError).toHaveBeenCalledWith(
expect.stringContaining(expectedConsoleError),
undefined
);
});
.... // other expects...
expect(messageError).toHaveBeenCalledWith({ message: expectedError }); |
It seems that in some cases you just can't get rid of this error. :( If you click on HyperlinkElement, you get to the
So if you use a HyperlinkElement in a test, you are doomed to this error. There could be two solutions:
and I use it as
|
I out comment ...
... in |
Yet-Another-Solution (TypeScript friendly). Only works if you have control over the IMO this is actually best as it explicitly removes side-effect code from your business logic. If you want, you can then
// adjust WindowLocation to accommodate all the window.location functionality you need
type WindowLocation = Pick<Location, 'reload' | 'assign' | 'pathname' | 'href' | 'origin'>;
export const windowLocation: WindowLocation = {
reload: () => window.location.reload(),
assign: (url) => window.location.assign(url),
get pathname() {
return window.location.pathname;
},
get href() {
return window.location.href;
},
get origin() {
return window.location.origin;
},
};
|
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:Is there a way to define a value of
window.location.search
using new version of jsdom?The text was updated successfully, but these errors were encountered: