[英]onBlur with useState hook not working in Jest?
I'm new into testing code with react and jest;我是用 react 和 jest 测试代码的新手; and jest is having a strange behavior towards hooks.
和 jest 对钩子有一种奇怪的行为。
This is my component.这是我的组件。 It has 2 useState hooks, linked to 2 functions.
它有 2 个 useState 钩子,链接到 2 个函数。
Just a simple component that works as it should.只是一个可以正常工作的简单组件。
import React, {useState} from 'react';
export const Test = () => {
const [cardNumber, setCardNumber] = useState('');
const [cardType, setCardType] = useState('');
const handleOnChange = (event) => {
setCardNumber(event.target.value);
};
const handleOnBlur = () => {
setCardType(cardNumber);
};
return (
<>
<input type="text" value={cardNumber} onChange={handleOnChange} onBlur={handleOnBlur} />
<p id="cn">{`CardNumber: ${cardNumber}`}</p>
<p id="ct">{`CardType: ${cardType}`}</p>
</>
);
};
This is the test:这是测试:
import React from 'react';
import {shallow} from 'enzyme';
import {Test} from '.';
import {act} from 'react-dom/test-utils';
describe('Sandbox Test', () => {
it('should set cardNumber when doing onChange', async () => {
const component = shallow(<Test />);
const inputComponent = component.find('input');
const value = {target: {value: '123456'}};
await act(async () => {
inputComponent.props().onChange(value);
await component.update();
});
const cardNumberComponent = component.find('#cn');
const cardTypeComponent = component.find('#ct');
expect(cardNumberComponent.text()).toEqual(`CardNumber: 123456`);
expect(cardTypeComponent.text()).toEqual(`CardType: `);
});
it('should set cardType when doing onBlur', async () => {
const component = shallow(<Test />);
const inputComponent = component.find('input');
const value = {target: {value: '123456'}};
await act(async () => {
inputComponent.props().onChange(value);
inputComponent.props().onBlur();
await component.update();
});
const cardNumberComponent = component.find('#cn');
const cardTypeComponent = component.find('#ct');
expect(cardNumberComponent.text()).toEqual(`CardNumber: 123456`);
expect(cardTypeComponent.text()).toEqual(`CardType: 123456`);
});
});
I dunno what's happening when the onBlur action is triggered (I know it's been triggered), but somehow, it doesn't trigger setCardType();我不知道触发 onBlur 操作时发生了什么(我知道它已被触发),但不知何故,它不会触发 setCardType(); and thus, this is the error I get when running the tests:
因此,这是我在运行测试时遇到的错误:
What am I doing wrong?我究竟做错了什么? Been trying to debug this for the past couple of hours, and I'm sincerely clueless about what to do.
在过去的几个小时里一直试图调试这个,我真的不知道该怎么做。
I think the call to .udpate()
recreates the node tree with all the updated data but doesn't automatically update references to nodes you get with find()
.我认为对
.udpate()
的调用使用所有更新的数据重新创建节点树,但不会自动更新对使用find()
获得的节点的引用。 So, the inputComponent
you have the moment you simulate the onBlur
event is the instance of the first render with an old version of the onBlur
handler with an empty value in cardNumber
state.因此,当您模拟
onBlur
事件时,您拥有的inputComponent
是第一次渲染的实例,使用旧版本的onBlur
处理程序,并且cardNumber
状态为空值。 You need to grab the input node again to get an updated instance before firing the onBlur
event.在触发
onBlur
事件之前,您需要再次抓取输入节点以获取更新的实例。
...
let inputComponent = component.find("input");
const value = { target: { value: "123456" } };
await act(async () => {
inputComponent.props().onChange(value);
await component.update();
inputComponent = component.find("input");
inputComponent.props().onBlur();
await component.update();
});
...
https://codesandbox.io/s/input-onchange-onblur-enzyme-kdg0u?file=/src/MyComponent.test.tsx https://codesandbox.io/s/input-onchange-onblur-enzyme-kdg0u?file=/src/MyComponent.test.tsx
I think this happens because you are calling .onChange()
and .onBlur()
in the same block of act()
.我认为这是因为您在同一块
act()
中调用.onChange()
和.onBlur()
act()
。 So both onChange
and onBlur
run with the closure on the same cardType
variable and only after that component re-renders with updated cardType
.所以
onChange
和onBlur
都在同一个cardType
变量上使用闭包运行,并且只有在该组件使用更新的cardType
重新渲染cardType
。
Try with splitting:尝试拆分:
it('should set cardType when doing onBlur', async () => {
const component = shallow(<Test />);
const inputComponent = component.find('input');
const value = {target: {value: '123456'}};
await act(async () => {
inputComponent.props().onChange(value);
await component.update();
});
await act(async () => {
inputComponent.props().onBlur();
await component.update();
});
const cardNumberComponent = component.find('#cn');
const cardTypeComponent = component.find('#ct');
expect(cardNumberComponent.text()).toEqual(`CardNumber: 123456`);
expect(cardTypeComponent.text()).toEqual(`CardType: 123456`);
});
Also I'm not sure you really need await
for act()
.另外,我不确定您是否真的需要
await
act()
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.