因此,我正在测试可更改状态的反应组件按钮单击。渲染组件时,我需要承诺解决,以便渲染按钮并因此使其可单击。我通过在组件状态得到更新时将按钮单击放置在setTimeout内来完成此操作。但是,在单击按钮后,由于已解决承诺,因此需要更新组件状态。我在下面举一个例子
class App extends component {
constructor(props){
this.state ={
hasError = false;
loading = true;
}
}
componentdidMount(){
this.apiGetFunc();
apiGetFunc(){
this.setState({hasError: false});
this.setState({loading = false});
}
onClickFunc{
this.middleWareCalltoAPI.then(
respone =>{ this.setState({hasError: false})},
errorRespone =>{ this.setState({hasError = true})};
)
}
renderer(){
return (
<Card>
{!this.state.hasError && !this.state.loading && (
<div>
<Button>
onClick = {this.onClickfunc}
</Button>
</div>
</Card>
)}
)
}
现在这是我的测试样子
test("Save user permissions", done => {
mock.onGet("anAPI.php").reply(200, mockData); //THIS IS NEEDED TO RENDER THE BUTTON
const wrapper = shallow(<App />);
setTimeout(() => {
wrapper.find("Button").simulate("click"); //THIS CLICK SHOULD CHANGE hasError to true
expect(wrapper.state.hasError).toEqual(true) //THIS FAILS
done();
}, 0);
});
我尝试嵌套setTimeouts,以便单击的诺言可以解决,但似乎不起作用。我试图尽可能地减少代码,以便于阅读。让我知道是否需要我提供更多背景信息。
编辑:使代码更类似于我实际拥有的
答案 0 :(得分:1)
上面的示例代码中有很多错误,我强烈建议您在尝试前进之前花一些时间做一些简单的React教程。
不过,这是一个有效的示例...
工作示例:https://codesandbox.io/s/xj53m8lwvz(您可以通过点击屏幕左下方附近的Tests
标签来运行测试)
api / fakeAPI.js
const data = [
{
userId: 1,
id: 1,
title: "delectus aut autem",
completed: false
},
{
userId: 1,
id: 2,
title: "quis ut nam facilis et officia qui",
completed: false
},
{
userId: 1,
id: 3,
title: "fugiat veniam minus",
completed: false
},
{
userId: 1,
id: 4,
title: "et porro tempora",
completed: true
},
{
userId: 1,
id: 5,
title: "laboriosam mollitia et enim quasi adipisci quia provident illum",
completed: false
}
];
export const fakeAPI = {
failure: () =>
new Promise((resolve, reject) => {
setTimeout(() => {
reject("No data was found!");
}, 1000);
}),
success: () =>
new Promise(resolve => {
setTimeout(() => {
resolve(data);
}, 1000);
})
};
components / App / App.js
import React, { Component } from "react";
import ShowData from "../ShowData/showData";
import ShowError from "../ShowError/showError";
import { fakeAPI } from "../../api/fakeAPI";
export default class App extends Component {
state = {
data: [],
hasError: "",
isLoading: true
};
componentDidMount = () => {
this.fetchData();
};
fetchData = () => {
fakeAPI
.success()
.then(data => this.setState({ isLoading: false, data: data }))
.catch(err => this.setState({ isLoading: false, hasError: err }));
};
handleClick = () => {
this.setState({ isLoading: true, data: [] }, () => {
fakeAPI
.failure()
.then(res => this.setState({ isLoading: false, hasError: "" }))
.catch(err => this.setState({ isLoading: false, hasError: err }));
});
};
render = () => (
<div className="app-container">
{this.state.isLoading ? (
<ShowLoading />
) : this.state.hasError ? (
<ShowError error={this.state.hasError} />
) : (
<ShowData data={this.state.data} handleClick={this.handleClick} />
)}
</div>
);
}
components / App / __ test __ / App.test.js (mountWrap
是一个自定义函数,可以在test/utils/index.js
中找到,而WaitForExpect是一种更简单的方法等待断言在玩笑的默认5秒超时时间内true
}
import React from "react";
import { mountWrap } from "../../../test/utils";
import WaitForExpect from "wait-for-expect";
import App from "../App";
const initialState = {
data: [],
hasError: "",
isLoading: true
};
const wrapper = mountWrap(<App />, initialState);
describe("App", () => {
it("renders without errors", () => {
expect(wrapper.find("div.app-container")).toHaveLength(1);
});
it("initally shows that it's loading", () => {
expect(wrapper.state("isLoading")).toBeTruthy();
expect(wrapper.find("div.loading")).toHaveLength(1);
});
it("renders data and shows an Update button", async () => {
await WaitForExpect(() => {
wrapper.update();
expect(wrapper.state("isLoading")).toBeFalsy();
expect(wrapper.find("div.data")).toHaveLength(5);
expect(wrapper.find("button.update")).toHaveLength(1);
});
});
it("shows an error once the button has been clicked", async () => {
wrapper.find(".update").simulate("click");
await WaitForExpect(() => {
wrapper.update();
expect(wrapper.state("isLoading")).toBeFalsy();
expect(wrapper.state("hasError")).toBe("No data was found!");
expect(wrapper.find("div.error")).toHaveLength(1);
});
});
});