Тестирование события mousedown вне React Component: Jest + Enzyme - PullRequest
0 голосов
/ 29 октября 2019

Я хочу написать тест с использованием Jest и Enzyme, который тестирует компонент, имеющий прослушиватель событий, так что когда происходит событие mousedown вне заданного html-элемента, происходит изменение (в этом примере значение состояния переключается),Я использую jest для того, чтобы смоделировать прослушиватель событий и имитировать событие mousedown, однако при попытке запустить этот тест я получаю следующее сообщение об ошибке:

TypeError: Не удалось выполнить «contains»на «Узле»: параметр 1 не относится к типу «Узел».

Очевидно, я думаю, что <div /> - это не то значение, которое я должен предоставить, когда я моделирую событие mousedown с map.mousedown({ target: <section /> });,Как правильно смоделировать событие mousedown, которое происходит за пределами моего компонента? Вы можете увидеть код ниже. Спасибо!

sampleComponent.jsx:

import * as React from 'react';

const SampleComponent = () => {
  const [state, setState] = React.useState(false);
  const ref = React.useRef(null);

  const handleClickOutside = (event) => {
    if (
      !ref.current.contains(event.target)
    ) {
      setState(true);
    }
  };

  React.useEffect(() => {
    document.addEventListener('mousedown', handleClickOutside);
    return () => document.removeEventListener('mousedown', handleClickOutside);
  });

  return (
    <div
      id="sample-div"
      ref={ref}
    >
      {`State value is: ${state}`}
    </div>
  );
};

export default SampleComponent;

sampleComponent.test.jsx:

import * as React from 'react';
import { mount } from 'enzyme';
import SampleComponent from './sampleComponent';

const setup = () => mount(<SampleComponent />);

test('testing mousedown', () => {
  const map = {};
  document.addEventListener = jest.fn((event, callback) => {
    map[event] = callback;
  });
  const wrapper = setup();
  expect(wrapper.find('#sample-div').text()).toBe('State value is: false');
  map.mousedown({ target: <section /> });
  expect(wrapper.find('#sample-div').text()).toBe('State value is: true');
});

1 Ответ

1 голос
/ 31 октября 2019

Вы не можете передать JSX как значение event.target. Поскольку вы используете document.addEventListener, это родное событие DOM. Вам необходимо передать собственный DOM, например document.createElement('a').

. Вот примеры тестов для вашего примера:

sampleComponent.tsx:

import React from 'react';

const SampleComponent = () => {
  const [state, setState] = React.useState(false);
  const ref = React.useRef(null);

  const handleClickOutside = event => {
    if (!(ref.current as any).contains(event.target)) {
      setState(true);
    }
  };

  React.useEffect(() => {
    document.addEventListener('mousedown', handleClickOutside);
    return () => document.removeEventListener('mousedown', handleClickOutside);
  });

  return (
    <div id="sample-div" ref={ref}>
      {`State value is: ${state}`}
    </div>
  );
};

export default SampleComponent;

sampleComponent.test.tsx:

import React from 'react';
import { mount } from 'enzyme';
import SampleComponent from './sampleComponent';
import { act } from 'react-dom/test-utils';

const setup = () => mount(<SampleComponent />);

beforeEach(() => {
  jest.resetAllMocks();
});
test('testing mousedown - 1', () => {
  const map: any = {};
  document.addEventListener = jest.fn((event, callback) => {
    map[event] = callback;
  });
  const wrapper = setup();
  expect(wrapper.find('#sample-div').text()).toBe('State value is: false');
  act(() => {
    map.mousedown({ target: document.createElement('a') });
  });
  expect(wrapper.find('#sample-div').text()).toBe('State value is: true');
  expect(document.addEventListener).toBeCalledTimes(2);
});

test('testing mousedown - 2', () => {
  const map: any = {};
  document.addEventListener = jest.fn((event, callback) => {
    map[event] = callback;
  });
  const wrapper = setup();
  expect(wrapper.find('#sample-div').text()).toBe('State value is: false');
  act(() => {
    map.mousedown({ target: wrapper.getDOMNode() });
  });
  expect(wrapper.find('#sample-div').text()).toBe('State value is: false');
  expect(document.addEventListener).toBeCalledTimes(1);
});

Результат модульного теста со 100% покрытием:

PASS  src/stackoverflow/58610112/sampleComponent.test.tsx (8.041s)
  ✓ testing mousedown - 1 (46ms)
  ✓ testing mousedown - 2 (3ms)

---------------------|----------|----------|----------|----------|-------------------|
File                 |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
---------------------|----------|----------|----------|----------|-------------------|
All files            |      100 |      100 |      100 |      100 |                   |
 sampleComponent.tsx |      100 |      100 |      100 |      100 |                   |
---------------------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        9.5s
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...