我怎样才能从 Cypress 测试中调用 fetch?
我正在使用 Cypress 。我有一个小的 React 应用和一个小型 Flask 后端。我希望我的测试能够调用后端来设置它将要操作的状态。我使用了 fetch。这工作正常。但 Cypress 很生气,不认为测试成功。我并不是一个真正的 javascript 开发人员,所以这可能很明显,但我不知道如何让它满意。
这是我的测试代码:
it.only("edits a job", async () => {
const now = new Date().getTime()
const title = `Edit-This-${now}`
const newTitle = `SUCCESS-EDIT-${now}`
const company = `Edit Company-${now}`
const link = `https://example.com/edit-me-${now}`
const status = "Edit Test"
const body = JSON.stringify({company, title, link, status})
await fetch('/add_job', {method: 'post', headers: {'Content-Type': 'application/json'}, body: body})
cy.visit("http://localhost:3000/jobs_list")
cy.contains(title)
cy.contains(company)
cy.contains(link)
cy.contains(status)
cy.get(`[name=edit-${title}`).click()
cy.get(`[value=${title}`).clear().type(newTitle)
cy.get(`[name=save-${newTitle}`).click()
cy.contains(newTitle)
console.log("what the heck")
})
这似乎工作正常。但最后,出现了 CypressError:
Cypress command timeout of 4530ms exceeded. (and Mocha's done() called multiple times)
我也尝试过不使用 async/await 并将步骤放在 fetch 之后的
then
中,但这没有帮助。将
done
传递给 it 块并在其末尾调用
done()
使其不运行任何内容。这是有道理的,因为 cypress 步骤看起来是同步的,但实际上并非如此,因此在执行任何步骤之前,它会命中
done()
。
使传递给
it
的函数不异步,并将 fetch 更改为
cy.request('POST', 'http://localhost:3000/add_job', {'Content-Type': 'application/json', company, title, link, status})
而不是
fetch
似乎有效,但我想了解原因。
使用
cy.request
而不是
fetch
。
https://docs.cypress.io/api/commands/request
cy.request({yourUri}).as("response"); // This takes care of the async task.
cy.get("@response").should((response) => {
// Carry on with the rest of your test
cy.get("some selector");
});
https://docs.cypress.io/guides/core-concepts/introduction-to-cypress.html#Chains-of-Commands
It’s very important to understand the mechanism Cypress uses to chain commands together. It manages a Promise chain on your behalf , with each command yielding a ‘subject’ to the next command, until the chain ends or an error is encountered. The developer should not need to use Promises directly, but understanding how they work is helpful!
您可以通过 Cypress.Promise
将项目添加到 Cypress 承诺链/队列中>
您可能可以使用 Cypress.Promise 包装您的
fetch
调用,但除非您有某些特定原因不使用,否则建议使用
cy.request
它。
// wrap null, so that you can use `then` to invoke a callback as an arbitrary command
// and return a Cypress.Promise - so that cypress will wait on it's result
// (or just use cy.request :))
cy.wrap(null).then(() => {
return new Cypress.Promise((resolve, reject) => {
try {
fetch(/*...*/).then(resolve);
} catch (e) {
reject(e);
}
})
})
您可以在 Cypress 测试中像这样使用带有 async/await 的 fetch:
it('should do something', () => {
const originalObject = { a: 1 }
const options = {
method: 'PUT',
body: JSON.stringify(originalObject),
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
},
}
cy.wrap(null).then(async () => {
const response = await fetch('/echo', options)
const echoedObject = await response.json()
expect(echoedObject).to.deep.eq(originalObject)
})
})