Jest: Expose jsdom to global environment

Created on 28 Dec 2016  Â·  17Comments  Â·  Source: facebook/jest

This is a question/discussion topic.

While discussing this issue #2453 and earlier conversation here #890 I came to conclusion that it may be worth exposing jsdom somehow to the environment. What do you think?

@cpojer @dmitriiabramov

Discussion Question

Most helpful comment

As of Jest 22/JSDom 11, using Object.defineProperty() no longer works on overriding location. This issue should be reopened and rediscussed.

All 17 comments

On my use case I need to change the window.location per it() so that jsdom behaves like modern browsers. This way the package.json testURL property/configuration wont be enough :(

As jsdom only allows this through the jsdom.changeURL() method, exposing jsdom would be the only way around to accomplish the use case.

window.location can be changed using Object.defineProperty(window, 'location', {value: '…'}). There is no need to expose jsdom for this.

@cpojer It does not have the same behavior than the jsdom.changeURL() one.

I have a script that does different things based on whether it is at the top level or not. window.top cannot be reconfigured without access to the jsdom instance created by Jest. How about also exposing the instance via something like jest.dom, which would allow us to use the reconfigure() method?

In our case, we have traditionally used Jest to test our React components using snapshots or, sometimes, more involved tests around events - those tests require a full mock DOM. Our components are held in a component library monorepo, and included in a separate project that does server-side rendering later on.

We recently had an issue where a component had an unchecked reference to document. This didn't cause any failures in our unit tests, but when we tried to integrate into our other project, the server-side rendering failed because it couldn't find window.

The solution to this is easy - just check if window is undefined - but we'd like to add some regression tests. Currently, I don't see a way to do this, because (as far as I know) we can only have jsdom enabled or disabled for all of our tests, not on a test-by-test basis. If we disable jsdom, all our previous tests will need to be re-written; if we leave it enabled, we can't test for this different category of errors.

Some sort of way to access and modify jsdom would be great, especially if it could help with this scenario.

@simon360 i think what you're looking for is this http://facebook.github.io/jest/blog/2017/05/06/jest-20-delightful-testing-multi-project-runner.html#multi-project-runner-configuration-overhaul
you can have two configs and run test twice in jsdom env and node env.
But honestly, writing tests for things like this is an overkill. If you use proper flow types, those kind of bugs will not be an issue at all.

Oh, that looks perfect. Thanks @aaronabramov!

(I'd love to use flow, but it isn't a good fit for our project right now. It's on our radar, but we just can't set the time aside for it at the moment.)

You can use @jest-environment jsdom in all tests requiring jsdom, and have node in package.json.

https://facebook.github.io/jest/docs/en/configuration.html#testenvironment-string

I am using a library that access "protocol", "host" and "port" on the location object.

@cpojer's work around does work if I do this:

Object.defineProperty(window.location, "protocol", {
    writable: true,
    value: "http:"
});
Object.defineProperty(window.location, "host", {
    writable: true,
    value: "localhost:14187"
});
Object.defineProperty(window.location, "port", {
    writable: true,
    value: "14187"
});

But fails if I try to do this

Object.defineProperty(window, "location", {
    writable: true,
    value: {
        protocol: "http:",
        host: "localhost:14187",
        port: "14187"
    }
});

I believe that exposing jsdom would actually make this solution a lot neater:

jest.jsdom.changeURL("http://localhost:14187")

Not planning to do this in jest-environment-jsdom. People can fork jest-environment-jsdom and build their own environment on top of it which will expose any globals people need.

Not planning to do this in jest-environment-jsdom. People can fork jest-environment-jsdom and build their own environment on top of it which will expose any globals people need.

FWIW, here's an up-to date template: https://github.com/mes/jest-environment-jsdom-external-scripts

What if I need to configure jsdom to have resources: "usable" in the configuration? or any other configuration that may be needed. Expoding jsdom configuration doesn't harm and it can provide a lot of flexibility. Any plan to expose the configuration? Or accept a pull request that enables this?

Then you can use a custom environment. resources: "usable" is supported in the env linked above your post

oh lol, thanks!

Changing the href location as suggested by @cpojer did not work for me, I had to follow the technique from @Mathspy

const url = "...";
Object.defineProperty(window.location, 'href', { value: url });

As of Jest 22/JSDom 11, using Object.defineProperty() no longer works on overriding location. This issue should be reopened and rediscussed.

@milesj see #5124

Was this page helpful?
0 / 5 - 0 ratings