如何使用 Enzyme 测试 onKeyPress 事件处理程序
How to test onKeyPress event handler with Enzyme
我有一个触发 onKeyPress 事件的测试:
const wrapper = mount(wrapper);
wrapper
.find('[data-test="test-number-input"]')
.find("input")
.simulate("keypress", { target: { value: "2" }, key: 2 });
这工作正常,但不会触发组件中的 onChange 事件(与浏览器中的 运行 不同)。据我了解,这种行为在 Enzyme 中是有意为之的。那么问题是我无法读取新值,因为状态是在 onChange 处理程序中设置的。那么测试我的 keyPress 处理程序行为的最佳方法是什么?
import React from "react";
import TextField from "@material-ui/core/TextField";
export default (props) => {
const minValue = props.minValue ?? 0;
const maxValue = props.maxValue ?? 100;
const step = props.step ?? 1;
const handleKeyPress = (evt) => {
const enteredCharCode = evt.which ? evt.which : evt.keyCode;
const newValue = evt.target.value + evt.key;
if (
enteredCharCode <= 47 ||
enteredCharCode >= 58 ||
newValue < minValue ||
newValue > maxValue
) {
evt.preventDefault();
}
};
const handleChange = (evt) => {
if (evt.target.value[0] === "0" && evt.target.value.length > 1) {
/* Prevent input if the first character is zero and the entered character is also zero.
else remove the first zero. */
(evt.which ? evt.which : evt.keyCode) === 48
? evt.preventDefault()
: (evt.target.value = evt.target.value.slice(1));
} else {
props.onChange(evt);
}
};
return (
<TextField
name={props.name}
label={props.labelText}
type="number"
defaultValue={props.defaultValue}
inputProps={{
min: minValue,
max: maxValue,
step: step,
}}
onKeyPress={handleKeyPress}
onChange={handleChange}
data-test="test-number-input"
/>
);
};
虽然在我看来这不是一个理想的解决方案,但我决定遵循这个 https://medium.com/@acesmndr/testing-react-functional-components-with-hooks-using-enzyme-f732124d320a 并将事件处理程序方法移到组件函数之外:
import React from "react";
import TextField from "@material-ui/core/TextField";
export const handleKeyPress = (evt, minValue, maxValue) => {
const enteredCharCode = evt.which ? evt.which : evt.keyCode;
const newValue = evt.target.value + evt.key;
if (
enteredCharCode <= 47 ||
enteredCharCode >= 58 ||
newValue < minValue ||
newValue > maxValue
) {
evt.preventDefault();
return;
}
return newValue;
};
export default (props) => {
const minValue = props.minValue ?? 0;
const maxValue = props.maxValue ?? 100;
const step = props.step ?? 1;
const handleChange = (evt) => {
if (evt.target.value[0] === "0" && evt.target.value.length > 1) {
/* Prevent input if the first character is zero and the entered character is also zero.
else remove the first zero. */
(evt.which ? evt.which : evt.keyCode) === 48
? evt.preventDefault()
: (evt.target.value = evt.target.value.slice(1));
} else {
props.onChange(evt);
}
};
return (
<TextField
name={props.name}
label={props.labelText}
type="number"
defaultValue={props.defaultValue}
inputProps={{
min: minValue,
max: maxValue,
step: step,
}}
onKeyPress={(evt) => handleKeyPress(evt, minValue, maxValue)}
onChange={handleChange}
data-test="test-number-input"
/>
);
};
所以现在我可以像这样测试事件处理程序:
expect(
handleKeyPress(
{
target: { value: "5" },
key: 2,
preventDefault: () => {},
},
1,
100
)
).toBe("52");
expect(
handleKeyPress(
{
target: { value: "99" },
key: 2,
preventDefault: () => {},
},
1,
100
)
).toBe(undefined);
我有一个触发 onKeyPress 事件的测试:
const wrapper = mount(wrapper);
wrapper
.find('[data-test="test-number-input"]')
.find("input")
.simulate("keypress", { target: { value: "2" }, key: 2 });
这工作正常,但不会触发组件中的 onChange 事件(与浏览器中的 运行 不同)。据我了解,这种行为在 Enzyme 中是有意为之的。那么问题是我无法读取新值,因为状态是在 onChange 处理程序中设置的。那么测试我的 keyPress 处理程序行为的最佳方法是什么?
import React from "react";
import TextField from "@material-ui/core/TextField";
export default (props) => {
const minValue = props.minValue ?? 0;
const maxValue = props.maxValue ?? 100;
const step = props.step ?? 1;
const handleKeyPress = (evt) => {
const enteredCharCode = evt.which ? evt.which : evt.keyCode;
const newValue = evt.target.value + evt.key;
if (
enteredCharCode <= 47 ||
enteredCharCode >= 58 ||
newValue < minValue ||
newValue > maxValue
) {
evt.preventDefault();
}
};
const handleChange = (evt) => {
if (evt.target.value[0] === "0" && evt.target.value.length > 1) {
/* Prevent input if the first character is zero and the entered character is also zero.
else remove the first zero. */
(evt.which ? evt.which : evt.keyCode) === 48
? evt.preventDefault()
: (evt.target.value = evt.target.value.slice(1));
} else {
props.onChange(evt);
}
};
return (
<TextField
name={props.name}
label={props.labelText}
type="number"
defaultValue={props.defaultValue}
inputProps={{
min: minValue,
max: maxValue,
step: step,
}}
onKeyPress={handleKeyPress}
onChange={handleChange}
data-test="test-number-input"
/>
);
};
虽然在我看来这不是一个理想的解决方案,但我决定遵循这个 https://medium.com/@acesmndr/testing-react-functional-components-with-hooks-using-enzyme-f732124d320a 并将事件处理程序方法移到组件函数之外:
import React from "react";
import TextField from "@material-ui/core/TextField";
export const handleKeyPress = (evt, minValue, maxValue) => {
const enteredCharCode = evt.which ? evt.which : evt.keyCode;
const newValue = evt.target.value + evt.key;
if (
enteredCharCode <= 47 ||
enteredCharCode >= 58 ||
newValue < minValue ||
newValue > maxValue
) {
evt.preventDefault();
return;
}
return newValue;
};
export default (props) => {
const minValue = props.minValue ?? 0;
const maxValue = props.maxValue ?? 100;
const step = props.step ?? 1;
const handleChange = (evt) => {
if (evt.target.value[0] === "0" && evt.target.value.length > 1) {
/* Prevent input if the first character is zero and the entered character is also zero.
else remove the first zero. */
(evt.which ? evt.which : evt.keyCode) === 48
? evt.preventDefault()
: (evt.target.value = evt.target.value.slice(1));
} else {
props.onChange(evt);
}
};
return (
<TextField
name={props.name}
label={props.labelText}
type="number"
defaultValue={props.defaultValue}
inputProps={{
min: minValue,
max: maxValue,
step: step,
}}
onKeyPress={(evt) => handleKeyPress(evt, minValue, maxValue)}
onChange={handleChange}
data-test="test-number-input"
/>
);
};
所以现在我可以像这样测试事件处理程序:
expect(
handleKeyPress(
{
target: { value: "5" },
key: 2,
preventDefault: () => {},
},
1,
100
)
).toBe("52");
expect(
handleKeyPress(
{
target: { value: "99" },
key: 2,
preventDefault: () => {},
},
1,
100
)
).toBe(undefined);