I need to retrieve an url from an email that was sent during the begining of a cypress scenario.
Waiting for the email and retrieving the url inside it is an asynchronous task, so I created a cypress plugin called "readMail" : it will take the email address as input, wait for the gmail api to actually have an email whose recipient is this address, then read the mail and return a promise resolving an url contained in the body of the email. This process works fine, because logs from the plugin do correctly show the extracted url.
My issue is to make this extractedUrl
available for later use as a param e.g. cy.visit(extractedUrl)
: outside the body of task(...).then(...)
, the variable is still not set.
Here is the code :
it('should generate correct email', () => {
const recipientEmail: string = '[email protected]';
const extractedUrl:string = '';
// ....scenario generating a email to '[email protected]'.....
cy.task('readMail', recipientEmail) // plugin logs "https://some.url.com" after a few seconds
.then((result:any) => {
extractedUrl= result;
console.log(result); // logs "https://some.url.com" in the terminal
cy.log("1:" + extractedUrl); // logs "1:https://some.url.com" in cypress UI
});
cy.log("2:"+ extractedUrl); // logs "2:" in cypress UI
console.log(extractedUrl); // logs nothing
cy.visit(extractedUrl);
});
I am probably missing something about how cypress handles async... I tried several different things : cy.wrap
and the cypress-wait-until
plugin but couldn't find any way to make those work.
Actually I found one way which was to declare extractedUrl
outside the test and begin a new test it('...', () => {...})
: then, extractedUrl
actually has the correct value at the beginning of the next test, but that is not ideal and I want to understand why.
Thanks for your help !
To do this I'm using wrap() to return a Chainable containing the value I want to return. Since wrap() is returning a Cypress. Chainable , we can call . then() on our commands.
By storing the variable outside of the test context using a getter and setter, you are able to pass variables between Cypress tests. This is especially useful in case you need to split up your test for cross-domain form submission and result verification.
Cypress can validate the text on an element with the help of jQuery text() method. This method shall help us to fetch the text content on the selected element. We can also put assertions on the text content of the element. cy.
To get baseUrl value use Cypress. config(). baseUrl or Cypress. config('baseUrl') .
TL;DR; put your entire code inside the then
callback
it('should generate correct email', () => {
const recipientEmail: string = '[email protected]';
const extractedUrl:string = '';
// ....scenario generating a email to '[email protected]'.....
// plugin logs "https://some.url.com" after a few seconds
cy.task('readMail', recipientEmail).then((result:any) => {
extractedUrl= result;
console.log(result); // logs "https://some.url.com" in the terminal
cy.log("1:" + extractedUrl); // logs "1:https://some.url.com" in cypress UI
cy.log("2:"+ extractedUrl); // logs "2:" in cypress UI
console.log(extractedUrl); // logs nothing
cy.visit(extractedUrl);
});
});
Contrary to what it seems, Cypress commands do not return promises, they return promise-like object and the execution queue is handle by the Cypress framework. That's the main reason some actions that would be logical when handling promises will not work.
More info here: Await-ing Cypress Chains #1417
You could also try cypress-promise, that is a plugin to change cypress promise-like objects into actual promises. More info here: Cypress.io — Using async and await by Nicholas Boll
You could also use alias in order to access the value:
it('should generate correct email', () => {
const recipientEmail: string = '[email protected]';
const extractedUrl:string = '';
// ....scenario generating a email to '[email protected]'.....
// plugin logs "https://some.url.com" after a few seconds
cy.task('readMail', recipientEmail).then((result:any) => {
extractedUrl= result;
cy.wrap(result).as('extractedUrl');
console.log(result); // logs "https://some.url.com" in the terminal
cy.log("1:" + extractedUrl); // logs "1:https://some.url.com" in cypress UI
});
cy.get('@extractedUrl').then((extractedUrl) => {
cy.log("2:"+ extractedUrl); // logs "2:" in cypress UI
console.log(extractedUrl); // logs nothing
cy.visit(extractedUrl);
})
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With