jest-globals
v0.1.7
Published
Mocks out global variables with Jest spies.
Downloads
5,169
Maintainers
Readme
🎭 jest-globals
Mocks out global variables with Jest spies.
Usage
jest-globals
sets up a collection of global mocks such as location
and navigator
and assigns them to global variables on globalThis
.
If a typeof window !== undefined
then it will assign the same values to window
as well.
Your source code can then still refer to global variables normally...
// Source file: ./example.ts
export function example() {
window.location.assign("/path");
}
...and your test files can import and use their test versions, as long as jest-globals
is imported before the code under test:
// Test file: ./example.test.ts
import { location } from "jest-globals";
import { example } from "./example";
describe("example", () => {
it("assigns /path to location", () => {
example();
expect(location.assign).toHaveBeenCalledWith("/path");
});
});
See #Custom Usage below for more details.
Available Globals
For each global available, you can import
it from jest-globals
directly.
addEventListener
import { addEventListener } from "jest-globals";
expect(addEventListener).toHaveBeenCalledWith("load", expect.any(Function));
alert
import { alert } from "jest-globals";
expect(alert).toHaveBeenCalledWith(expect.any(Function));
blur
import { blur } from "jest-globals";
expect(blur).toHaveBeenCalledTimes(1);
close
import { close } from "jest-globals";
expect(close).toHaveBeenCalledTimes(1);
confirm
import { confirm } from "jest-globals";
expect(confirm).toHaveBeenCalledTimes(1);
dispatchEvent
import { dispatchEvent } from "jest-globals";
expect(dispatchEvent).toHaveBeenCalledTimes(1);
focus
import { focus } from "jest-globals";
expect(focus).toHaveBeenCalledTimes(1);
getSelection
Use createMockSelection
to create a valid Selection
with stub data for any field not explicitly provided.
import { createMockSelection, getSelection } from "jest-globals";
getSelection.mockReturnValue(
createMockSelection({
focusOffset: 2,
})
);
localStorage
localStorage
is assigned an instance of a MockStorage
class of assigned items under an items
Map
.
import { localStorage } from "jest-globals";
localStorage.setItem("powerLevel", "9001");
expect(localStorage.setItem).toHaveBeenCalledWith("powerLevel", "9001");
expect(localStorage.items.getItem("powerLevel")).toEqual("9001");
MockStorage
'sconstructor
includes abeforeEach(() => this.items.clear())
.
location
import { location } from "jest-globals";
expect(location.assign).toHaveBeenCalledWith("/path");
matchMedia
import { createMockMediaQueryList, matchMedia } from "jest-globals";
matchMedia.mockReturnValue(
createMockMediaQueryList({
//
})
);
moveBy
import { moveBy } from "jest-globals";
expect(moveBy).toHaveBeenCalledWith(12, 34);
navigator
import { navigator } from "jest-globals";
navigator.mockUserAgent.mockReturnValue("Mozilla/123");
navigator.clipboard.readText.mockResolvedValue("It's over 9,000!");
expect(navigator.serviceWorker.register).toHaveBeenCalled();
open
import { open } from "jest-globals";
expect(open).toHaveBeenCalledWith("https://hi.joshuakgoldberg.com");
performance
import { performance } from "jest-globals";
performance.now.mockReturnValue(9001);
postMessage
import { postMessage } from "jest-globals";
expect(postMessage).toHaveBeenCalledWith("Is anybody out there?", "*");
print
import { print } from "jest-globals";
expect(print).toHaveBeenCalledTimes(1);
prompt
import { prompt } from "jest-globals";
expect(prompt).toHaveBeenCalledWith("Hello my baby");
removeEventListener
import { removeEventListener } from "jest-globals";
expect(removeEventListener).toHaveBeenCalledWith(expect.any(Function));
requestAnimationFrame
import { requestAnimationFrame } from "jest-globals";
expect(requestAnimationFrame).toHaveBeenCalledWith(expect.any(Function));
requestIdleCallback
import { requestIdleCallback } from "jest-globals";
expect(requestIdleCallback).toHaveBeenCalledWith(expect.any(Function));
resizeBy
import { resizeBy } from "jest-globals";
expect(resizeBy).toHaveBeenCalledWith(12, 34);
resizeTo
import { resizeTo } from "jest-globals";
expect(resizeTo).toHaveBeenCalledWith(123, 456);
scrollBy
import { scrollBy } from "jest-globals";
expect(scrollBy).toHaveBeenCalledWith(12, 34);
scrollTo
import { scrollTo } from "jest-globals";
expect(scrollTo).toHaveBeenCalledWith(123, 456);
sessionStorage
sessionStorage
is assigned an instance of a MockStorage
class that keeps track of assigned items under an items
member of type Map<string, string>
:
import { sessionStorage } from "jest-globals";
sessionStorage.setItem("powerLevel", "9001");
expect(sessionStorage.setItem).toHaveBeenCalledWith("powerLevel", "9001");
expect(sessionStorage.items.getItem("powerLevel")).toEqual("9001");
MockStorage
'sconstructor
includes abeforeEach(() => this.items.clear())
.
setImmediate
import { setImmediate } from "jest-globals";
expect(setImmediate).toHaveBeenCalledWith(expect.any(Function));
stop
import { stop } from "jest-globals";
expect(stop).toHaveBeenCalledTimes(1);
top
window.top
is by default a reference to an identical mock window object, except its .top
references itself.
import { top } from "jest-globals";
expect(top.postMessage).toHaveBeenCalledWith("I'll be back one day", "*");
Strongly Typed Usage
jest-globals
is written in TypeScript and generally type safe.
Imported objects from jest-globals
are typed as having jest.Mock
s for their functions with parameters and return types corresponding to their original mocks.
Global mocks that return complex original objects therefore require mockReturnValue
and co. to be provided with objects that match up to the original type:
import { getSelection } from "jest-globals";
getSelection.mockReturnValue({
focusOffset: 2,
});
// Error: Argument of type '{ focusOffset: number; }' is not assignable to parameter of type 'Selection'.
// Type '{ focusOffset: number; }' is missing the following properties from type 'Selection': anchorNode, anchorOffset, focusNode, focusOffset, and 16 more.
Each of these APIs has a corresponding createMock*
function exported by jest-globals
that takes in a Partial
of the returned type and fills in any missing fields:
import { createMockSelection, getSelection } from "jest-globals";
getSelection.mockReturnValue(
createMockSelection({
focusOffset: 2,
})
);
What's Not Provided
The following global members are complex enough that they warrant their own dedicated packages:
document
:jest-environment-jsdom
fetch
:fetch-mock
/fetch-mock-jest
getComputedStyle
: similar todocument
XMLHTTPRequest
: usefetch
instead 😄
Custom Usage
Auto-Sorted Involvement
If you'd like jest-globals
to run after library code, it may be inconvenient to also have a linter plugin thatt auto-sorts your imports.
// example.test.js
import "jest-globals"; // runs first 😔
import userEvent from "@testing-library/user-event";
If your configuration puts imports under a prefix such as ~/
last, you can create a file whose sole purpose is to import jest-globals
:
// tests/globals
export * from "jest-globals";
// example.test.js
import userEvent from "@testing-library/user-event";
import "~/tests/globals"; // runs last 😌
Another (less type safe) workaround is to use Jest's moduleNameMapper
to allow importing under a name like zzzest-globals
, pushing it alphabetically below other absolute imports:
{
"moduleNameMapper": {
"^zzzest-globals$": "jest-globals"
}
}
// example.test.js
import userEvent from "@testing-library/user-event";
import "zzzest-globals"; // runs last 😌
Permanent Involvement
If you'd like jest-globals
to always be run before all your files, you can include it in your setupFilesAfterEnv
:
// ./jest.setup.js
require("jest-globals");
Development
Requires:
After forking the repo from GitHub:
git clone https://github.com/<your-name-here>/jest-globals
cd jest-globals
yarn
Contribution Guidelines
We'd love to have you contribute!
Check the issue tracker for issues labeled accepting prs
to find bug fixes and feature requests the community can work on.
If this is your first time working with this code, the good first issue
label indicates good introductory issues.
Please note that this project is released with a Contributor Covenant. By participating in this project you agree to abide by its terms. See CODE_OF_CONDUCT.md.