Jest: Testing window.location.reload
If you use TypeScript with Jest:
Idea
- Create a copy and then delete
window
'slocation
property. - Now set
location
property withreload
function mocked. - Set the original value back when test completes.
Code: TypeScript 3.x and below
const location: Location = window.location;
delete window.location;
window.location = {
...location,
reload: jest.fn()
};
// <code to test>
// <code to test>
// <code to test>
expect(window.location.reload).toHaveBeenCalledTimes(1);
jest.restoreAllMocks();
window.location = location;
Code: TypeScript 4+
TypeScript 4 has stricter checks (which is a good thing), so I am not really sure if there's a way to do this other than to suppress the error using @ts-ignore
or @ts-expect-error
.
WARNING: Suppressing TypeScript validations can be ð´dangerousð´.
const location: Location = window.location;
// WARNING:
// @ts-ignore and @ts-expect-error suppress TypeScript validations by ignoring errors.
// Suppressing TypeScript validations can be ð´dangerousð´.
// @ts-ignore
delete window.location;
window.location = {
...location,
reload: jest.fn()
};
// <code to test>
// <code to test>
// <code to test>
expect(window.location.reload).toHaveBeenCalledTimes(1);
jest.restoreAllMocks();
window.location = location;
You can also simplify Murtaza Hussain's solution to
describe('refreshPage', () => {
const { reload } = window.location;
beforeAll(() => {
Object.defineProperty(window, 'location', {
writable: true,
value: { reload: jest.fn() },
});
});
afterAll(() => {
window.location.reload = reload;
});
it('reloads the window', () => {
refreshPage();
expect(window.location.reload).toHaveBeenCalled();
});
});
Updated Answer (November 2021)
Package:
"jest": "^26.6.0"
"@testing-library/jest-dom": "^5.11.4"
Build: create-react-app 4
describe("test window location's reload function", () => {
const original = window.location;
const reloadFn = () => {
window.location.reload(true);
};
beforeAll(() => {
Object.defineProperty(window, 'location', {
configurable: true,
value: { reload: jest.fn() },
});
});
afterAll(() => {
Object.defineProperty(window, 'location', { configurable: true, value: original });
});
it('mocks reload function', () => {
expect(jest.isMockFunction(window.location.reload)).toBe(true);
});
it('calls reload function', () => {
reloadFn(); // as defined above..
expect(window.location.reload).toHaveBeenCalled();
});
});
Note: Updated answer because the the old answer
wasn't supported with latest jest version used in CRA.
Old answer
Here’s the solution but refactored for better organization:
describe('test window location\'s reload function', () => {
const { reload } = window.location;
beforeAll(() => {
Object.defineProperty(window.location, 'reload', {
configurable: true,
});
window.location.reload = jest.fn();
});
afterAll(() => {
window.location.reload = reload;
});
it('mocks reload function', () => {
expect(jest.isMockFunction(window.location.reload)).toBe(true);
});
it('calls reload function', () => {
reloadFn(); // as defined above..
expect(window.location.reload).toHaveBeenCalled();
});
});
Thanks :)