How to mock window.location.href with Jest in React?

10,295

Solution 1

I ended up with the following on React 16 and Jest 24.

describe("usePageTracking", () => {
  let location;
  const mockLocation = new URL("https://example.com");

  beforeEach(() => {
    location = window.location;
    mockLocation.replace = jest.fn();
    // You might need to mock other functions as well
    // location.assign = jest.fn();
    // location.reload = jest.fn();
    delete window.location;
    window.location = mockLocation;
  });

  afterEach(() => {
    window.location = location;
  });

  // ...
});

See also:

Solution 2

Use Object.defineProperty() to define a getter for window.location.

E.g.

usePageTracking.ts:

import { useEffect } from 'react';

export const usePageTracking = (): void => {
  useEffect(() => {
    console.log(window.location.href);
  }, []);
};

Example.tsx:

import React from 'react';
import { usePageTracking } from './usePageTracking';

export function Example() {
  usePageTracking();
  return <div>example</div>;
}

Example.test.tsx:

import React from 'react';
import { Example } from './Example';
import { render } from '@testing-library/react';

describe('Example', () => {
  it('should pass', () => {
    Object.defineProperty(window, 'location', {
      get() {
        return { href: 'stackoverflow.com' };
      },
    });
    render(<Example />);
  });
});

test result

 PASS  examples/63409476/Example.test.tsx (11.048 s)
  Example
    ✓ should pass (39 ms)

  console.log
    stackoverflow.com

      at examples/63409476/usePageTracking.ts:5:13

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        12.768 s

package versions:

"jest": "^26.6.3",
"ts-jest": "^26.4.4",

jest.config.js:

module.exports = {
  preset: 'ts-jest/presets/js-with-ts',
}
Share:
10,295
thisismydesign
Author by

thisismydesign

Updated on June 08, 2022

Comments

  • thisismydesign
    thisismydesign about 2 years

    I'm testing functionality that is not supposed to run locally and need to mock window.location.href:

    const usePageTracking = (): void => {
      const location = useLocation();
    
      useEffect(() => {
        if (!window.location.href.includes("localhost")) {
          ReactGA.initialize("UA-000000-01");
          ReactGA.pageview(window.location.pathname + window.location.search);
        }
      }, []);
    };
    

    In my tests:

    describe("usePageTracking", () => {
      it("initializes ReactGA", () => {
        render(<Example />);
        expect(ReactGA.initialize).toHaveBeenCalled();
      });
    
      it("tracks page view", () => {
        render(<Example />);
        expect(ReactGA.pageview).toHaveBeenCalledWith("/");
      });
    });
    

    Note: there's a related question around Vue but it wasn't clear to me if the solutions apply to React as well (some just didn't work).

  • scottwernervt
    scottwernervt almost 3 years
    Object.defineProperty() worked perfectly with typescript!