Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pass parameter to jest.mock

I have a mock as follows

jest.mock('react-hook-inview', () => {
  const setRef = jest.fn();
  const observer = jest.fn();
  const intersecting = true;
  const entry = {
    y: 0,
  };
  return [setRef, intersecting, entry, observer];
});

Here I would like to change the intersecting value. How can I change that from one test to another? I was trying to use something like a factory:

const inView = (intersecting) => {
  jest.mock('react-hook-inview', () => {
    const setRef = jest.fn();
    const observer = jest.fn();
    const entry = {
      y: 0,
    };
    return [setRef, intersecting, entry, observer];
  });
}

and use it like

  it('is invisible by default', () => {
    const text = 'Test';
    const { container } = render(<Reveal>{text}</Reveal>);
    inView(false);
    expect(container.firstChild).not.toBeVisible();
  });

  it('is visible when in view', () => {
    const text = 'Test';
    const { container } = render(<Reveal>{text}</Reveal>);
    inView(true);
    expect(container.firstChild).toBeVisible();
  });

however this throws

The module factory of `jest.mock()` is not allowed to reference any out-of-scope variables.
Invalid variable access: intersecting

does anybody have an idea?

cheers!

EDIT:

My solution for now is to mock it like this

import ReactHookInview from 'react-hook-inview';

jest.mock('react-hook-inview', () => ({
  useInView: jest.fn().mockImplementation(() => {
    const setRef = jest.fn();
    const observer = jest.fn();
    const intersecting = false;
    const entry = {
      boundingClientRect: {
        y: 0,
      },
    };
    return [setRef, intersecting, entry, observer];
  }),
}));

and in my test I overwrite like this:

ReactHookInview.useInView.mockImplementation(() => {
  const setRef = jest.fn();
  const observer = jest.fn();
  const intersecting = true;
  const entry = {
    boundingClientRect: {
      y: 1,
    },
  };
  return [setRef, intersecting, entry, observer];
});

but that's not really beautiful

like image 760
ccc1da70-5e63-4879-a4cb-adb604 Avatar asked Jan 15 '20 15:01

ccc1da70-5e63-4879-a4cb-adb604


People also ask

What does Jest fn () do?

The Jest library provides the jest. fn() function for creating a “mock” function. An optional implementation function may be passed to jest. fn() to define the mock function's behavior and return value.

How do you mock data in Jest?

In Jest, Node. js modules are automatically mocked in your tests when you place the mock files in a __mocks__ folder that's next to the node_modules folder. For example, if you a file called __mock__/fs. js , then every time the fs module is called in your test, Jest will automatically use the mocks.

How do you call a mock function in Jest?

You can create a namespace that you export as the default object and call b using the namespace. This way, when you call jest. mock it will replace the b function on the namespace object. const f = require('./f'); jest.


1 Answers

You can mock your library as you have already done, import it and explicitly set it's value. And then before have two different sets of tests:

jest.mock('react-hook-inview', /* as above */ );

import rhi from 'react-hook-inview';

describe('my implementation', () => {

  describe('while intersecting', () => {
    let result;
    beforeAll(() => {
      rhi[1] = true;
      result = myImplementationUsingIntersecting();
    });

    it('should result X', () => {
      expect(result).toEqual(X);
    });
  });

  describe('while NOT intersecting', () => {
    let result;
    beforeAll(() => {
      rhi[1] = false;
      result = myImplementationUsingIntersecting();
    });

    it.todo('should result Y');
  });
})

working example

Edit 2: in order to properly mock a React hook

since the react hooks are functions that return stuff you'll can mock it like this

jest.mock('react-hook-inview', () => jest.fn());
// and you can take it's reference with import
import useInView from 'react-hook-inview';
// and then you can mock it's return value as array
beforeAll(() => {
  useInView.mockReturnValue(['a', true, 'b', 'c']);
  result = myImplementationUsingIntersecting();
})
like image 182
Teneff Avatar answered Oct 06 '22 23:10

Teneff