我有一个可以在localhost上运行的组件。如果输入冠军的字母,则onInputHandler(input)会将组件的状态更改为有效的冠军的名称。不幸的是,当我用酶进行测试时,组件的状态永远不会改变(保持默认状态)。我很乐意提供任何建议。当我使用数组设置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);
});
答案 0 :(得分:1)
尝试更换
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之类的工具来模拟后端,而不是在测试中调用实际的端点。