【问题标题】:Testing mousedown event outside React Component: Jest + Enzyme在 React 组件之外测试 mousedown 事件:Jest + Enzyme
【发布时间】:2020-02-24 20:26:19
【问题描述】:

我想使用 Jest 和 Enzyme 编写一个测试来测试具有事件侦听器的组件,这样当给定 html 元素之外发生 mousedown 事件时,就会发生更改(在本示例中,状态值被切换) .我正在使用 jest 来模拟事件侦听器并模拟 mousedown 事件,但是,当我尝试运行此测试时,我收到以下错误消息:

TypeError:无法在“节点”上执行“包含”:参数 1 不是“节点”类型。

显然,当我使用map.mousedown({ target: <section /> }); 模拟 mousedown 事件时,我认为<div /> 不是我应该提供的正确值。如何正确模拟在我的组件之外发生的 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');
});

【问题讨论】:

    标签: javascript reactjs jestjs enzyme


    【解决方案1】:

    您不能将 react 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
    

    【讨论】:

      猜你喜欢
      • 2017-02-12
      • 2018-08-20
      • 2018-05-02
      • 1970-01-01
      • 2017-04-13
      • 2021-06-24
      • 1970-01-01
      • 2021-01-08
      • 1970-01-01
      相关资源
      最近更新 更多