Is it possible in Cypress.io to gather results of multiple assertions inside .then
construction so that results can be used outside .then
?
Based on below example - if I have some pages that I would like to smoke-test (to check eg. if code is different than 404) how to gather information about them? How to verify results all together in one smoke test?
Please look at this simple piece of code that shows the problem:
describe('Smoke tests for some pages', () => {
it('should be able to view page that was loaded correctly', () => {
// Arrange:
const pageAddressList = [
'https://en.wikipediaaa.org',
'https://en.wikipedia.org'];
const errors = Array();
// Act:
pageAddressList.forEach((pageAddress) => {
cy.request(pageAddress).then((response) => {
// check response and add some error to errors if needed
})
});
// Assert:
// check if errors is empty
});
});
EDIT 2: This solution was written for Cypress ~3.6.0 or thereabouts so it's possible that newer versions of Cypress work very differently internally, even if you fix some superficial incompatibilities of this code.
EDIT: often someone suggests using Promise.all
, which is not a correct solution. Cypress chainer objects aren't Promises/A+-compatible, they simply appear to be promises because they implement .then
interface. That's why Promise.all
is able to consume an array of chainer objects, but that's it. The resolution values passed to Promise.all().then
callback is not going to be what you expect (see https://github.com/cypress-io/cypress/issues/915).
You can use a helper I've suggested in a similar answer:
// put this in cypress/support/index.js
const chainStart = Symbol();
cy.all = function ( ...commands ) {
const _ = Cypress._;
const chain = cy.wrap(null, { log: false });
const stopCommand = _.find( cy.queue.commands, {
attributes: { chainerId: chain.chainerId }
});
const startCommand = _.find( cy.queue.commands, {
attributes: { chainerId: commands[0].chainerId }
});
const p = chain.then(() => {
return _( commands )
.map( cmd => {
return cmd[chainStart]
? cmd[chainStart].attributes
: _.find( cy.queue.commands, {
attributes: { chainerId: cmd.chainerId }
}).attributes;
})
.concat(stopCommand.attributes)
.slice(1)
.flatMap( cmd => {
return cmd.prev.get('subject');
})
.value();
});
p[chainStart] = startCommand;
return p;
}
usage:
it('test', () => {
const urls = [
'https://en.wikipediaaa.org',
'https://en.wikipedia.org'
];
cy.all(
...urls.map(url => cy.request(url))
).then(responses => {
responses.forEach( resp => {
expect(resp.status).to.eq(200);
});
});
});
That being said, you can also do this:
const urls = [
'https://en.wikipediaaa.org',
'https://en.wikipedia.org'
];
let passes = 0;
urls.forEach( url => {
cy.request(url).then( resp => {
if ( resp.status === 200 ) passes++;
});
});
cy.then(() => {
expect(passes).to.eq(urls.length);
});
The cy.all
helper atop is really useful if you want to access the results without having to keep around globals and accessing them from a cy.then()
callback --- but like I've shown in the last example, everything can be worked around using just vanilla cypress.
Or, if you don't need responses at all, you can simply do:
const urls = [
'https://en.wikipediaaa.org',
'https://en.wikipedia.org'
];
urls.forEach( url => {
cy.request(url).its('status').should('eq', 200);
});
You can collect them all and act when only all responses are ready with Cypress.Promise.all
it.only('Gathering results', () => {
const urls = ['https://google.com',
'https://en.wikipedia.org']
const requests = urls.map(url => {
console.log(`a request sent to ${url}`)
return new Cypress.Promise(resolve => {
cy.request(url).then(resopnse => {
console.log(`'Response from ${url}`)
resolve(resopnse)
})
})
})
Cypress.Promise.all(requests).then(responses => {
// process responses
console.log("All responses ready")
console.log(responses.map(response => response.redirects.toString()))
})
})
I don't have the complete context of what you're doing. Apparently, it seems you're using Cypress as a monitoring tool that regularly checks the availability of some external sites and send out notifications. If so, I would say no, Cypress is a testing framework to write tests of your own services/systems.
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