2

What I've been trying is to render a component with shallow, which is provided by enzyme.

The component is using useHistory from react-router-dom.

const baseMatch: match<{ id: string }> = { /* path, url, params */};
const location = createLocation(baseMatch.url);

describe('MyComponent', () => {
  const baseProps = {
    history: createMemoryHistory(),
    location: createLocation(baseMatch.url),
    match: baseMatch
  };

  beforeEach(() => {
    jest.mock('react-router-dom', () => ({
      useHistory: jest.fn()
    }));
  });

  afterEach(() => { jest.clearAllMocks() });

  it('renders blah blah', () => {
    const wrapper = shallow(<MyComponent {...baseProps} />);
    // testing MyComponent here...
  });

I referred to this post, and put jest.mock in the same way.

However, this results in TypeError: Cannot read property 'history' of undefined.

The console says:

MyComponent › renders blah blah

    TypeError: Cannot read property 'history' of undefined

      24 | const MyComponent = (props: IProps) => {
      25 |   console.log('useHistory', useHistory);
    > 26 |   let history = useHistory();

Strangely, the console.log in line 25 above prints the implementation of useHistory (In other words, it's not undefined).

Clearly, useHistory isn't mocked. I suspect that useHistory can't be mocked with shallow (In the post above, the poster was using mount()).

However, I'm not 100% sure because I can't find if shallow is compatible with useHistory or not from the docs of enzyme and react-router.

Is it possible to use shallow with useHistory? Any advice will be appreciated.

Hiroki
  • 3,893
  • 13
  • 51
  • 90

1 Answers1

2

From the docs:

Note: In order to mock properly, Jest needs jest.mock('moduleName') to be in the same scope as the require/import statement.

So instead of mocking react-router-dom in beforeEach - try having it at the top scope:

jest.mock('react-router-dom', () => ({
  useHistory: jest.fn()
}));

const baseMatch: match<{ id: string }> = { /* path, url, params */};
const location = createLocation(baseMatch.url);


describe('MyComponent', () => {
  const baseProps = {
    history: createMemoryHistory(),
    location: createLocation(baseMatch.url),
    match: baseMatch
  };

...
Daniel
  • 6,194
  • 7
  • 33
  • 59