我有一个可以在本地主机上运行的组件。如果您输入冠军的字母,onInputHandler(input) 会将组件的状态更改为有效冠军的名称。不幸的是,当我用 enzyme 进行测试时,组件的状态永远不会改变(保持默认状态)。我很乐意提供任何建议。当我用数组设置 this.statechampionsList 时,结果是相同的。通常,该数组在 componentDidMount() 之后用 getChampionsList() 填充。
export class ChooseChampion extends React.Component {
constructor() {
super();
this.state = {
championSelected: "Choose champion",
championsList: []
};
this.onInputHandler = this.onInputHandler.bind(this);
this.getFilteredChampion = this.getFilteredChampion.bind(this);
}
componentDidMount() {
this.getChampionsList();
}
getChampionsList = () => {
fetch('/champions-list')
.then(res => res.json())
.then(champions => this.setState({ championsList: champions }))
}
onInputHandler(event) {
if (event.target.value === "") {
this.setState({
championSelected: "Choose champion"
});
} else {
const input = event.currentTarget.value;
const filteredChampion = this.getFilteredChampion(input)
this.setState({
championSelected: filteredChampion
});
}
}
getFilteredChampion(input) {
let oneFilteredChampion = this.state.championsList.find(champion => champion.toLowerCase().includes(input.toLowerCase()))
if (oneFilteredChampion) {
return oneFilteredChampion;
} else {
return "Wrong name!"
}
}
render() {
return (
<div className="choose-champion-container">
<div className="role-and-caption inactive">
<img className="role-icon" src={require(`../assets/images/${this.props.lane}_icon.png`)} alt={this.props.lane} />
<span className="role-caption">{this.props.lane}</span>
</div>
<div className="champion-avatar-and-caption">
<ChampionAvatar currentChampion={this.state.championSelected} championsList={this.state.championsList} />
<ChampionCaption currentChampion={this.state.championSelected} championsList={this.state.championsList} />
</div>
<div className="search-container">
<button type="submit" className="search-button"><img src={SearchIcon} className="search-icon" alt="Search" /></button>
<input type="text" placeholder="Find champion..." name="search" onInput={this.onInputHandler} />
</div>
</div>
)
};
}
这是我的测试声明:
const lanes = ["Top", "Jungle", "Middle", "Bottom", "Support"]
const app = <ChooseChampion lane={lanes[Math.floor(Math.random() * (5))]} />;
it('Should change the state after change the input value', () => {
const newValue = 'Ahri';
const wrapper = mount(app);
const input = wrapper.find('input');
input.value = newValue;
wrapper.update();
expect(input.value).toEqual(newValue);
expect(wrapper.state('championSelected')).toEqual(newValue);
});
最佳答案
尝试更换
input.value = newValue;
与
input.simulate('change', {target: {value: newValue}});
或
input.simulate('input', {target: {value: newValue}});
要实际触发事件(onChange
或 onInput
),您需要模拟 DOM 事件。仅更改输入中的值不会触发 React 监听器。
另一件事是您在 componentDidMount 中进行提取。这是一个异步调用。 mount
之后,冠军列表将不会被填充。有几种方法可以等待它。您可以使用wait-for-expect或者自己写一个类似的函数。因此,最终测试应该类似于:
it('Should change the state after change the input value', () => {
const newValue = 'Ahri';
const wrapper = mount(app);
await waitForExpect(() => {
expect(wrapper.state('championsList')).to.be.not.empty;
});
const input = wrapper.find('input');
input.simulate('change', {target: {value: newValue}});
wrapper.update();
expect(input.value).toEqual(newValue);
expect(wrapper.state('championSelected')).toEqual(newValue);
});
注意:您可能更喜欢使用 nock 这样的工具模拟后端而不是在测试中调用实际端点。
关于javascript - React/Enzyme 组件函数不更新状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61487884/