Reputation: 2803
In my Cypress test suite I have a command that makes an API call to an email service looking for an email with a particular subject and returns the content of that email.
Cypress.Commands.add('getMostRecentEmail', subject => {
const requestUrl = new URL('api/mails', 'localhost')
requestUrl.port = '3000'
requestUrl.searchParams.append('subject', subject)
// TODO: wait for the following request to return a non-empty response.body
return cy.request('GET', requestUrl.toString()).then(response => {
return response.body[0].content[0].value
})
})
This works fine when I run the test locally, but when the test is run on CI, it fails the first time, but succeeds when Cypress automatically retries the test. Presumably this is because the email has not yet been received the first time an attempt to is made to retrieve it (the email is sent immediately before the code above executes).
response.body
is the number of matching emails returned by the service, and the first time a request is made, this is empty, so response.body[0]
is undefined
.
Cypress reports this test as "flakey" because it doesn't succeed the first time it is attempted.
To fix this, I would like to instead wait for the request to return a non-empty response before retrieving the content of the first email.
Upvotes: 0
Views: 1824
Reputation: 1919
Take a look at https://slides.com/bahmutov/email-testing presentation. In particular, the blog post https://www.cypress.io/blog/2021/05/24/full-testing-of-html-emails-using-ethereal-accounts/#retry-email-task talks how to retry getting the email, since it can happen only after some unknown time.
Upvotes: 1
Reputation: 1140
Create a function for your request that you can call recursively:
function makeRequestRecursively() {
cy.request('GET', requestUrl.toString()).then(response => {
let value = response.body[0].content[0].value;
if (response.body[0].content[0].value != undefined) {
return value;
}
else {
// Recursively call the function after 0.5 seconds. You can adjust or remove this.
setTimeout(function (){
return makeRequestRecursively();
}, 500);
}
}
}
Replace:
return cy.request('GET', requestUrl.toString()).then(response => {
return response.body[0].content[0].value
})
With:
return makeRequestRecursively()
Upvotes: 0