使用酶,模拟 keydown 事件不适用于事件动态添加到元素的元素
Using enzyme, simulating keydown event is not working on element where event is dynamically added to element
我有一个运行良好的组件,我正在尝试使用 jest 和 enzyme 编写一些测试。
const handleEvent = (e: KeyboardEvent) => {
if(e.keyCode === 27)
console.log('Escape event');
}
const Component = () => {
const ref = useRef(null);
useEffect(() => {
ref.current?.addEventListener('keydown', handleEvent);
return () => {
ref.current?.removeEventListener('keydown', handleEvent);
}
}, []);
return (
<div ref={ref}> Some inner elements </div>
)
}
这是我试图模拟逃跑事件的测试
it('simulate escape event', () => {
const component = mount(<Component />);
component.simulate('keydown', { keyCode: 27 });
// assertion of things that are handled on escape
});
这不是触发逃生事件。但是,当我将事件处理程序直接附加到 dom 上的组件时,相同的测试正在模拟转义事件并且似乎工作正常。
const handleEvent = (e: KeyboardEvent) => {
if(e.keyCode === 27)
console.log('Escape event');
}
const Component = () => {
const ref = useRef(null);
return (
<div ref={ref} onKeyDown={handleEvent}> Some inner elements </div>
)
}
有人能告诉我为什么在事件动态附加到组件时模拟不起作用,但在直接将其添加到 dom 时模拟却工作正常吗?我试图在各种文章中搜索此术语,但一无所获。
提前致谢。
酶模拟的工作方式类似于 .simulate("click") 实际上会查找 onClick 函数并将参数传递给它,没有 'actual' 点击继续
所以 enzyme 不会模拟直接添加事件的触发...你可能需要自己去派发事件。
component.getDOMNode() 获取 DOM 节点,dispatchEvent 应该在该节点上工作。如下所示
it('simulate escape event', () => {
const component = mount(<Component />);
const event = new Event('keydown');
event.keyCode = 27;
component.getDOMNode().dispatchEvent(event);
// assertion of things that are handled on escape
});
我看到的另一个问题是 useEffect 中的依赖数组。
当 dom 元素有时在反应重新渲染之间发生变化时,删除 useEffect 中的空数组依赖项以保证其安全。
useEffect(() => {
ref.current?.addEventListener('keydown', handleEvent);
return () => {
ref.current?.removeEventListener('keydown', handleEvent);
}
});
您仅在安装组件时附加 eventHandler。
但是 DOM 元素可能会在 React 渲染之间发生变化,因此您实际上应该在所有 useEffects 中附加 eventListener,它在 React 渲染和 DOM React 生命周期更新后触发。
你也可以依赖 callBackRefs,如果你认为 DOM 元素上会有一些昂贵的东西并且不希望它在每个 useEffects 上都 运行。
对于只附加事件侦听器,这个没有依赖数组的 useEffect 应该没问题。
我有一个运行良好的组件,我正在尝试使用 jest 和 enzyme 编写一些测试。
const handleEvent = (e: KeyboardEvent) => {
if(e.keyCode === 27)
console.log('Escape event');
}
const Component = () => {
const ref = useRef(null);
useEffect(() => {
ref.current?.addEventListener('keydown', handleEvent);
return () => {
ref.current?.removeEventListener('keydown', handleEvent);
}
}, []);
return (
<div ref={ref}> Some inner elements </div>
)
}
这是我试图模拟逃跑事件的测试
it('simulate escape event', () => {
const component = mount(<Component />);
component.simulate('keydown', { keyCode: 27 });
// assertion of things that are handled on escape
});
这不是触发逃生事件。但是,当我将事件处理程序直接附加到 dom 上的组件时,相同的测试正在模拟转义事件并且似乎工作正常。
const handleEvent = (e: KeyboardEvent) => {
if(e.keyCode === 27)
console.log('Escape event');
}
const Component = () => {
const ref = useRef(null);
return (
<div ref={ref} onKeyDown={handleEvent}> Some inner elements </div>
)
}
有人能告诉我为什么在事件动态附加到组件时模拟不起作用,但在直接将其添加到 dom 时模拟却工作正常吗?我试图在各种文章中搜索此术语,但一无所获。 提前致谢。
酶模拟的工作方式类似于 .simulate("click") 实际上会查找 onClick 函数并将参数传递给它,没有 'actual' 点击继续
所以 enzyme 不会模拟直接添加事件的触发...你可能需要自己去派发事件。
component.getDOMNode() 获取 DOM 节点,dispatchEvent 应该在该节点上工作。如下所示
it('simulate escape event', () => {
const component = mount(<Component />);
const event = new Event('keydown');
event.keyCode = 27;
component.getDOMNode().dispatchEvent(event);
// assertion of things that are handled on escape
});
我看到的另一个问题是 useEffect 中的依赖数组。 当 dom 元素有时在反应重新渲染之间发生变化时,删除 useEffect 中的空数组依赖项以保证其安全。
useEffect(() => {
ref.current?.addEventListener('keydown', handleEvent);
return () => {
ref.current?.removeEventListener('keydown', handleEvent);
}
});
您仅在安装组件时附加 eventHandler。
但是 DOM 元素可能会在 React 渲染之间发生变化,因此您实际上应该在所有 useEffects 中附加 eventListener,它在 React 渲染和 DOM React 生命周期更新后触发。
你也可以依赖 callBackRefs,如果你认为 DOM 元素上会有一些昂贵的东西并且不希望它在每个 useEffects 上都 运行。
对于只附加事件侦听器,这个没有依赖数组的 useEffect 应该没问题。