Передать параметр в jest.mock - PullRequest
6 голосов
/ 15 января 2020

У меня есть макет следующим образом

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];
});

Здесь я хотел бы изменить значение intersecting. Как я могу изменить это от одного теста к другому? Я пытался использовать что-то вроде фабрики:

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];
  });
}

и использовать это как

  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();
  });

однако это бросает

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

У кого-нибудь есть идея?

ура!

РЕДАКТИРОВАТЬ:

Мое решение на данный момент состоит в том, чтобы сделать это так

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];
  }),
}));

и в моем тесте я перезаписать так:

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

но это не очень красиво

Ответы [ 2 ]

1 голос
/ 16 января 2020

Вы можете смоделировать вашу библиотеку, как вы уже сделали, импортировать ее и явно установить ее значение. И затем, прежде чем сделать два разных набора тестов:

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');
  });
})

рабочий пример

Редактировать 2: чтобы правильно смоделировать ловушку React

, поскольку ловушки реагирования - это функции, которые возвращают вещи, которые вы можете высмеивать так

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();
})
0 голосов
/ 15 января 2020

Как сказано в комментариях jest.mock вызовы подняты, этого не происходит с jest.doMock https://jestjs.io/docs/en/jest-object#jestdomockmodulename -factory-options

Попробуйте заменить его в своем коде, вы должен иметь возможность доступа к переменной внешней области видимости.

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