Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jest: Testing window.location.reload

How do I write a test that makes sure that the method reloadFn does in fact reload the window? I found this resource but I am unclear on how to expect a window reload when writing a test when that window reload happens in a given function. Thanks for the help!

const reloadFn = () => {
  window.location.reload(true);
}
like image 604
Jimmy Avatar asked Apr 16 '19 16:04

Jimmy


People also ask

Can I use window location reload?

You can use the location. reload() JavaScript method to reload the current URL. This method functions similarly to the browser's Refresh button. The reload() method is the main method responsible for page reloading.

What is location reload ()?

The location. reload() method reloads the current URL, like the Refresh button.

What is the difference between location reload () and window location reload ()?

location. reload(true); reloads the page from the server instead of from the cache, window. location. reload(); would do the same thing as location.


3 Answers

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 :)

like image 160
Murtaza Hussain Avatar answered Oct 19 '22 20:10

Murtaza Hussain


If you use TypeScript with Jest:

Idea

  1. Create a copy and then delete window's location property.
  2. Now set location property with reload function mocked.
  3. 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;
like image 24
Sachin Joseph Avatar answered Oct 19 '22 19:10

Sachin Joseph


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();
    });
  });
like image 12
Jennie Quinton Avatar answered Oct 19 '22 19:10

Jennie Quinton