简体   繁体   English

如何使用 Jest/Enzyme 在 React 中测试 keydown 事件?

[英]How to test keydown event in React with Jest/Enzyme?

I have the following component:我有以下组件:

import React, { Component } from 'react';

export class Cars extends Component {
  constructor(props) {
    super(props);
    this.state = {
      activeSearch: true
    };
  }

  componentDidMount() {
    document.addEventListener('keydown', this.escFunction, false);
  }

  escFunction(event) {
    if (event.keyCode === 27) this.skipCar();
  }

  skipCar() {
    this.setState({ activeSearch: false });
  }

  render() {
    return <div></div>;
  }
}

I wrote following tests to check if this function is called:我写了以下测试来检查这个 function 是否被调用:

test('should close', () => {
    let events = {};
    document.addEventListener = jest.fn((event, cb) => {
      events[event] = cb;
    });

    const wrapper = shallow(<Cars {...props} />);
    const instance = wrapper.instance();
    const spy = jest.spyOn(instance, 'skipCar');

    events.keyDown({ keyCode: 27 });

    expect(spy).toHaveBeenCalled();
    expect(wrapper.state().activeSearch).toBe(false);
  });

but when I run this test I have an error:但是当我运行这个测试时,我有一个错误:

TypeError: events.keyDown is not a function

    > 82 |     events.keyDown({ keyCode: 27 });
         |            ^

Why I have this error????为什么我有这个错误??? How can I run this test to check if method is run?如何运行此测试以检查方法是否运行?

You should use event.keydown({ keyCode: 27 }) , then your code works fine.您应该使用event.keydown({ keyCode: 27 }) ,然后您的代码可以正常工作。

Here is the working unit test for your code:这是您的代码的工作单元测试:

index.jsx : index.jsx

import React, { Component } from 'react';

export class Cars extends Component {
  constructor(props) {
    super(props);
    this.state = {
      activeSearch: true
    };
    this.escFunction = this.escFunction.bind(this);
  }

  componentDidMount() {
    document.addEventListener('keydown', this.escFunction, false);
  }

  escFunction(event) {
    if (event.keyCode === 27) this.skipCar();
  }

  skipCar() {
    this.setState({ activeSearch: false });
  }

  render() {
    return <div></div>;
  }
}

index.spec.jsx : index.spec.jsx

import React from 'react';
import { shallow } from 'enzyme';
import { Cars } from './';

const props = {};

test('should close', () => {
  let events = {};
  document.addEventListener = jest.fn((event, cb) => {
    events[event] = cb;
  });

  const wrapper = shallow(<Cars {...props} />);
  const instance = wrapper.instance();
  const spy = jest.spyOn(instance, 'skipCar');

  events.keydown({ keyCode: 27 });

  expect(spy).toHaveBeenCalled();
  expect(wrapper.state().activeSearch).toBe(false);
});

Unit test result:单元测试结果:

 PASS  src/stackoverflow/58748367/index.spec.jsx (7.988s)
  ✓ should close (10ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        9.214s

Source code: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/58748367源码: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/58748367

A better approach is not to mock addEventListener but to trigger the event on the document.更好的方法不是模拟addEventListener而是触发文档上的事件。

var event = new KeyboardEvent('keydown', {'keyCode': 37});
document.dispatchEvent(event);

This will allow you mimic real life scenario.这将允许您模拟现实生活中的场景。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM