Do you want to request a feature or report a bug?
feature
What is the current behavior?
At the beginning, I searched window
through jest document, but got nothing...
So I was using window
from 'jsdom' like this:
import { JSDOM } from 'jsdom'
const { window } = new JSDOM()
global.window = window
But, my module didn't use this window
.
After that, I found global
is what I want from StackOverflow
I used that and it worked~
But...It's kind of weird.
I can't find anything mention that in docs.
And I'm thinking maybe jest can change the window
that module used to global.window
.
So we can use window
instantly rather than global
...
jsdom is used automatically. Don't import it in your test.
Yeah, I already know that...
I just thought jest document should mention that global
is window
...
I met same issue.
test("should not defined global.window", function() {
console.log(typeof global.window !== "undefined" ? "global.window is defined" : "No window");
expect(global.window).toBeUndefined();
});
// It fail on Node.js + Jest.
Reproduce repository: azu/jest-expose-global-window
I notice that some library doesn't work on Node.js + Jest default env.
For example, https://github.com/alizain/ulid doen't work.
I've avoided this issue by setting "testEnvironment": "node"
.
For any future googlers: global
is window
. So if you want to use the window
object, don't use global.window
— just use global
.
I had some tests where I needed to see if window.print
was called and also if document.title
was used somewhere. However, if you set anything global, it will also be present in other tests. I used the following shared helpers to temporarily set some global properties.
export async function withGlobalProperty(
propertyName,
tempValue,
handler = () => {}
) {
const original = global[propertyName];
global[propertyName] = tempValue;
await handler();
global[propertyName] = original;
}
export async function withGlobalDocumentProperty(propertyName, tempValue, handler = () => {}) {
const original = global.document[propertyName];
global.document[propertyName] = tempValue;
await handler();
global.document[propertyName] = original;
}
Then in a test:
import { withGlobalProperty, withGlobalDocumentProperty } from "./shared.js";
test("should trigger `window.print()` when clicked", () => {
const mockPrint = jest.fn();
withGlobalProperty("print", mockPrint, () => {
const wrapper = mount(<Component />);
wrapper.simulate("click");
expect(mockPrint).toHaveBeenCalledTimes(1);
});
});
test("should default the `text` to `document.title`", () => {
const title = "My Title";
withGlobalDocumentProperty("title", title, () => {
const wrapper = mount(<AnotherComponent />);
expect(
wrapper.find(`a[href*="text=${encodeURIComponent(title)}"]`)
).toHaveLength(1);
});
});
There may be a cleaner/safer way to do all this :)
@robertwbradford Your test will not fail if there is an error. The promise needs to complete before the result is returned to it
, so your test will always pass if written without async/await
. That's if you use async/await
in your withGlobalProperty
. If you remove all async/await
, then no problem.
❌ Example of a test which should fail but pass anyway with your example. It throws an error which is swallowed UnhandledPromiseRejectionWarning: Unhandled promise rejection.
export async function withGlobalProperty(
propertyName,
tempValue,
handler = () => {}
) {
const original = global[propertyName];
global[propertyName] = tempValue;
await handler();
global[propertyName] = original;
}
test('returns the same value for a string defined in window', () => {
withGlobalProperty('acme', { value: true }, () => {
expect(window.acme.value).toBe(false)
})
})
✔️The test should be rewritten adding async/await
:
export async function withGlobalProperty(
propertyName,
tempValue,
handler = () => {}
) {
const original = global[propertyName];
global[propertyName] = tempValue;
await handler();
global[propertyName] = original;
}
test('returns the same value for a string defined in window', async () => {
await withGlobalProperty('acme', { value: true }, () => {
expect(window.acme.value).toBe(false)
})
})
✔️... or no async/await
should be used at all:
export function withGlobalProperty(
propertyName,
tempValue,
handler = () => {}
) {
const original = global[propertyName];
global[propertyName] = tempValue;
handler();
global[propertyName] = original;
}
test('returns the same value for a string defined in window', () => {
withGlobalProperty('acme', { value: true }, () => {
expect(window.acme.value).toBe(false)
})
})
Good catch, @sebastienfi . Thanks.
Most helpful comment
For any future googlers:
global
iswindow
. So if you want to use thewindow
object, don't useglobal.window
— just useglobal
.