Javascript 使用react测试库测试react热键

Javascript 使用react测试库测试react热键,javascript,reactjs,testing,hotkeys,react-testing-library,Javascript,Reactjs,Testing,Hotkeys,React Testing Library,我无法触发热键(运行玩笑)。演示组件: import React from 'react'; import { HotKeys } from 'react-hotkeys'; class TestComponent extends React.Component { constructor(props) { super(props); this.state = { enterClicked: false }; } render() { const { en

我无法触发热键(运行玩笑)。演示组件:

import React from 'react';
import { HotKeys } from 'react-hotkeys';

class TestComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = { enterClicked: false };
  }

  render() {
    const { enterClicked } = this.state;
    return (
      <HotKeys
        handlers={{
          enter: (e) => {
            console.log('ENTER', e);
            this.setState({ enterClicked: true });
          },
        }}
      >
        <input placeholder="input" type="text" />
        {enterClicked && <div>Enter clicked</div>}
      </HotKeys>
    );
  }
}

export default TestComponent;
从“React”导入React;
从“反应热键”导入{HotKeys};
类TestComponent扩展了React.Component{
建造师(道具){
超级(道具);
this.state={enterClicked:false};
}
render(){
const{enterClicked}=this.state;
返回(
{
console.log('ENTER',e);
this.setState({enterClicked:true});
},
}}
>
{enterClicked&&enterClicked}
);
}
}
导出默认测试组件;
下面是一个测试:

import React from 'react';
import { cleanup, fireEvent, render, waitForElement } from 'react-testing-library';

import TestComponent from './TestComponent';

afterEach(cleanup);

describe('Test', () => {
  it('Hotkeys', () => {
    const { debug, getByPlaceholderText, getByText } = render(<TestComponent />);
    const inputNode = getByPlaceholderText('input');
    fireEvent.keyDown(inputNode, { key: 'Enter', keyCode: 13, code: 13, bubbles: true });
    debug();
    waitForElement(() => getByText('Enter clicked'));
  });
});
从“React”导入React;
从“react testing library”导入{cleanup,fireEvent,render,waitForElement};
从“./TestComponent”导入TestComponent;
每次之后(清理);
描述('测试',()=>{
它('热键',()=>{
const{debug,getByPlaceholderText,getByText}=render();
const inputNode=getByPlaceholder文本(“输入”);
keyDown(inputNode,{key:'Enter',keyCode:13,code:13,bubbles:true});
调试();
waitForElement(()=>getByText('Enter clicked');
});
});
以下是我的jest设置文件:

/* global jest */
import { JSDOM } from 'jsdom';
import 'jest-localstorage-mock';
import dotenv from 'dotenv';

dotenv.config({ path: '../.env' });

const jsdom = new JSDOM('<!doctype html><html><body></body></html>', { url: 'https://example.com' });
const { window } = jsdom;
window.location.reload = jest.fn();
window.location.assign = jest.fn();

function copyProps(src, target) {
  const props = Object.getOwnPropertyNames(src)
    .filter((prop) => typeof target[prop] === 'undefined')
    .reduce(
      (result, prop) => ({
        ...result,
        [prop]: Object.getOwnPropertyDescriptor(src, prop),
      }),
      {},
    );
  Object.defineProperties(target, props);
}

if (!window.attachEvent) {
  // eslint-disable-next-line func-names
  const attachEvent = function(on, callback) {
    on = on.substring(2, on.length);
    return this.addEventListener(on, callback);
  };

  window.Element.prototype.attachEvent = attachEvent;
}

if (!window.detachEvent) {
  // eslint-disable-next-line func-names
  const detachEvent = function(on, callback) {
    on = on.substring(2, on.length);
    return this.removeEventListener(on, callback);
  };

  window.Element.prototype.detachEvent = detachEvent;
}

global.window = window;
global.document = window.document;
global.navigator = {
  userAgent: 'node.js',
  platform: 'Mac',
};
copyProps(window, global);

global.fetch = require('jest-fetch-mock');

global.requestAnimationFrame = (cb) => {
  setTimeout(cb, 0);
};

global.cancelAnimationFrame = (cb) => {
  setTimeout(cb, 0);
};
/*全球笑话*/
从'JSDOM'导入{JSDOM};
导入“jest localstorage mock”;
从“dotenv”导入dotenv;
dotenv.config({path:'...env'});
const jsdom=new jsdom(“”,{url:'https://example.com' });
const{window}=jsdom;
window.location.reload=jest.fn();
window.location.assign=jest.fn();
功能copyProps(src、target){
const props=Object.getOwnPropertyNames(src)
.filter((prop)=>typeof target[prop]==='undefined')
.减少(
(结果,道具)=>({
…结果,
[prop]:Object.getOwnPropertyDescriptor(src,prop),
}),
{},
);
对象。定义属性(目标、道具);
}
如果(!window.attachEvent){
//eslint禁用下一行函数名
const attachEvent=函数(打开,回调){
开=开子串(2,开长度);
返回此.addEventListener(打开,回调);
};
window.Element.prototype.attachEvent=attachEvent;
}
如果(!window.detachEvent){
//eslint禁用下一行函数名
const detachEvent=函数(打开,回调){
开=开子串(2,开长度);
返回此.removeEventListener(打开,回调);
};
window.Element.prototype.detachEvent=detachEvent;
}
global.window=窗口;
global.document=window.document;
global.navigator={
userAgent:'node.js',
平台:“Mac”,
};
复制道具(窗口、全局);
global.fetch=require('jest-fetch-mock');
global.requestAnimationFrame=(cb)=>{
设置超时(cb,0);
};
global.cancelAnimationFrame=(cb)=>{
设置超时(cb,0);
};

有什么想法吗?

以下是我是如何做到这一点的:

我在
热键
-组件本身上放置了一个测试id:

<HotKeys
  data-testid="hot-keys-id"
  ...

我遇到了同样的问题。但不幸的是,你的解决方案对我不起作用。我有最新版本的
react热键
。如果我弄明白了,我会再插话的。但如果您有更新,请分享!:)抱歉,没有更新!现在我倾向于非渲染单元测试+e2e测试,而不是反应渲染测试,因为它们太麻烦了。但我很想听到你发现的一切!天哪,我犯了个愚蠢的错误。我没有在
热键
元素上使用
waitForElement
(正如您所做的那样),以确保它在调用
dispatchEvent
之前已呈现。我不知怎么错过了。谢谢你!现在工作。
const hotkeys = await waitForElement(() => getByTestId('hot-keys-id'));
hotkeys.focus();

const keyDownEvent = new Event('keydown');
keyDownEvent.keyCode = 13;
keyDownEvent.key = 'Enter';
keyDownEvent.code = 13;

hotkeys.dispatchEvent(keyDownEvent);