jest: window.location.href can't be changed in tests.
Hi @cpojer,
This is actually more of a jsdom@8
issue…see tmpvar/jsdom#1388, but I want to pin here as well so Jest picks up whatever solution jsdom comes up with.
Previously with jest-cli@0.8/jsdom@7.x
you could write a test like this:
jest.autoMockOff()
jest.setMock('../lib/window', window)
jest.mock('cookies-js')
jest.mock('query-string')
jest.mock('superagent')
describe(['@utils/auth - When an AJAX response returns:'
].join('')
, function () {
beforeEach(function () {
window.location.href = 'http://quux.default.com'
var queryString = require('query-string')
queryString.__setMockParseReturns([{
'access_token': '1234foo',
'expires_in': '9999'
}])
})
it(['should set a redirect token and goto platform ',
'when the AJAX request returns 401.'
].join('')
, function () {
var superagent = require('superagent')
superagent.__setMockAjaxResponses([
[null, { 'status': 401 }]
])
var href = window.location.href
var auth = require('../index.js')
auth.login(function (res) {})
var Cookies = require('cookies-js')
var config = require.requireActual('../config')
expect(decodeURIComponent(window.location.href)).toBe([
config.loginUrl,
config.loginServiceLogin,
'?client_id=',
config.clientId,
'&response_type=token',
'&redirect_uri=',
config.clientRedirectUri
].join(''))
expect(Cookies.__getMockCookieData()[config.clientId + '_state_locationAfterLogin']).toBe(escape(href))
})
And that test would pass. Since jsdom@8
this is no longer possible and these tests fail.
Seems like jsdom is looking at some type of capability, just wanted to make sure that Jest will pick up that capability when it is available.
About this issue
- Original URL
- State: closed
- Created 8 years ago
- Reactions: 4
- Comments: 74 (12 by maintainers)
Commits related to this issue
- WIP https://github.com/facebook/jest/issues/890#issuecomment-357603080 — committed to josephfrazier/reported-web by josephfrazier 6 years ago
You are right, this is indeed a jsdom issue. At Facebook, what we have done to work around this, is use this:
this works for us, however we are still on jsdom 7 internally.
I’ll close this, as I believe the
Object.defineProperty
way of doing things is fine. If that doesn’t work for you in jsdom 8, I’m happy to reopen it.It stopped working in Jest 22.0.1
Error message:
old ticket but for those still having this issue we’ve started using
window.location.assign()
instead so in our tests we can mock theassign
function like so…This worked for me.
I found this post to be very helpful: https://www.ryandoll.com/post/2018/3/29/jest-and-url-mocking
"In your Jest configuration, make sure to set the following:
Then in your beforeEach() section for your test, change the path as needed by using history.pushState().
Voila! Now you change out your path for any test, without having to override any jsdom configurations as others suggest in the thread mentioned above. Not sure on which thread I found this solution on, but kuddos to the dev that posted it!"
@thymikee I saw that issue but thought that the proposition was rejected. @cpojer I misread your example and mixed it up with other related to this problem, where people suggested to use
Object.defineProperty(window, 'location', {value: 'url'});
. Thank you!I need to change not only the href, so I wrote simple method, that may be useful for someone who will read this thread:
this worked for me
on jest version 23.6.0
@Mike-Tran That works! Thanks you! However, I didn’t need the
testURL
orbeforeEach
. I just did:window.history.pushState({}, 'Test Title', '/test.html?query=true');
And now I don’t have to use
Object.defineProperty
anymore 😅Stop posting this, it does not work on jest": “^22.4.2”
Hi, I have used this in the test, i delete the global state and create a new one with jsdom… :
Btw @cpojer I start at FB on 1May… ;P
Posted it on other ticket, but I’ll post it here:
Found nice solution for Jest 21.2.1
Ok, so far the easiest solution around this is: Go into your Jest settings (for example I’ll use package.json):
"jest": { "testURL": "http://localhost" }
Now you will have access to window object and then you can set URL to whatever you like during tests.
Hopefully this helps someone.
To get this working as of June 2019 I had to do this:
this works for me on jest 24.9.0
@cpojer, I can’t seem to figure out what I need to click on to reopen this issue…
Is there anyway in
jest
environment for one to calljsdom.changeUrl(window, url)
as described here https://github.com/tmpvar/jsdom#changing-the-url-of-an-existing-jsdom-window-instance injest-cli@15.1.1
?This approach works as of Sep 27, 2019: https://stackoverflow.com/a/54034379/1344144
This TypeScript is working for me on Jest 24.0.0 and Node 10.15.0:
src/setupTests.ts
src/setupTests.test.ts
src/testUtils.ts
src/testUtils.test.ts
If you just want some other url than
about:blank
, you can usetestURL
config.I use this…
Thanks @FelipeBohnertPaetzold. I was using
location.host
in my code, so found I needed a full location object, so the following worked better for me, rather than having to manually pass each location property:@msholty-fd you could try this approach:
I had to make code async in order to get this to work because I was running code inside a promise.
so is working now 😃
this creates a Location with all the original functionality, but it’s mockable:
Excellent solution!!! Thank you very much! @Mike-Tran I wanted a short and not invasive solution like this!
@SimenB I’m not convinced that Jest should fix this. JSDOM should allow
window.location.assign()
to work as intended and reconfigure the output ofwindow.location.href
etc.In TypeScript 4.1.3, this (as well as all other suggestions to
delete
anything onwindow
) gives me:class SSOtestComponent extends React.Component {
}
module.exports = SSOtestComponent;
i am write the unit test case using enjyme and jest how will write the condition window.location …pls give the answer
I have this at the top of my JSDOM setup file:
Another solution works for me currently without writing
jsdom
:testURL
injest.config.js
no matter the value:In your test file:
Learned from: https://www.ryandoll.com/post/2018/3/29/jest-and-url-mocking. Thansk to Ryan!
Or better yet…
Fixed it by setting “testURL”: “http://localhost/” in Jest config (I’m using latest version). By default it’s “about:blank” and it was causing JSDOM error (you cannot change “about:blank” url to something else).
Resources: http://jestjs.io/docs/en/configuration#testurl-string https://github.com/jsdom/jsdom/issues/1372
thanks @simon360
that’s what I did 😉 I used
jsdom.reconfigure
to setup different initialurls
in my tests, and whenever I need to change url in code (not test), I usewindow.location.assign
and mocked it. which worked for me.just for people who may/will run into the same issue, to set the url for your jsdom
note that this will set url for all your tests; if you want a different url in some particular tests, use
jsdom.reconfigure
api; if you need to change url on the fly outside of unit test code (i.e. production code), you need to usewindow.location.assign
and mock it.add this to the global file.
delete global.window.location; global.window.location = “”;
@Mike-Tran You rock! That totally worked, so simple. I didn’t even have to use the testURL setting.
I don’t know if this would help someone, but this is what I am currently doing.
Write a redirect function and use that instead. So in testing env, it will rely on jsdom.reconfigure url to change url part.
I use it like this
After that, in your test, it can be sth like this
Probably part of my JSDOMTestWrapper can help somebody
@tzvipm @j-u-p-iter thanks for the 👍. I just released
@jedmao/storage
and@jedmao/location
, which are both completely agnostic of Jest. You should be able tospyOn
the appropriate methods without writing any additional tests, as the npm packages come completely tested.If your goal is to mock the
window
object, here is my (not so elegant, but it works) solution:Create an interface (not sure if interface is the right word, but I hope you get the point) class:
In your actual code, swap out
window
with the interface method’s, e.g.win
Then, in your jest tests, you just mock them out so jsdom doesn’t complain. You can even assert them:
I ended up doing this which worked:
@bochen2014 this issue has more information on how to use the newer version of jsdom: #5124
tl;dr: you can mock
window.location.assign()
, or you can use thejest-environment-jsdom-global
, which will allow you to reconfigure jsdom in flight.thanks @SimenB for your reply.
No I was talking about
base url
noturl
. I have code that will dowindow.location.href="/login"
and when runningjest
,jsdom
throw exception complaining/login
is not a valid urlI checked the source code of
jsdom
and realised this is because I don’t have a base url setup ( this is equivalent of typing “/login” in browser URL bar without a base address).with
jsdom
, normally we can set up base url viabut because
jest
set upjsdom
, it is beyond our control.— update: I suppose I can explicitly add
jsdom
as dependency and configurejsdom
manually. but I’m not sure if it’s the recommended way to do itI then found a solution which is to substitute
window.location.href=
withwindow.location.assign
and mockassign
function and it worked for meHmm, we might need to somehow allow people to call
reconfigure
. https://github.com/tmpvar/jsdom/blob/05a6deb6b91b4e02c53ce240116146e59f7e14d7/README.md#reconfiguring-the-jsdom-with-reconfiguresettings@matt-dalton what’s your URL? do you have testURL set in your
jest-config.json
or does it initialize asabout:blank
?I’m trying to migrate our tests from Mocha+Chai+Sinon.js to Jest and can’t figure out how to change location for a particular test. Jest 19.x uses JSDom 9.12 that does not allow to change location using
Object.defineProperty
trick. Also, I can’t usejsdom.changeURL()
because of the reasons described in tmpvar/jsdom#1700. @cpojer what about implementing some proxy method tojsdom.changeURL()
in Jest?