Reputation: 7653
Say I want to retrieve the values of two Cypress aliases and use it in my test case. How do I do so without nesting them in the following manner?
cy.get('@alias1')
.then((alias1) => {
cy.get('@alias2').then((alias2) => {
someFunctionThatUsesBothAliases(alias1, alias2);
})
})
Upvotes: 20
Views: 10808
Reputation: 10018
The code @KondasamyJayaraman refers to appears to be broken, I see it relies on internal Cypress implementation from about 5 years ago.
Here is a simpler one-line version which uses a standard Cypress custom command:
it('custom command to get all alias values', () => {
Cypress.Commands.add('aliases', function(aliasNames) {
return aliasNames.map(a => this[a])
})
cy.wrap('a').as('foo');
cy.wrap('b').as('bar');
cy.wrap('c').as('baz');
cy.aliases(['foo', 'bar', 'baz']).then(values => {
expect(values).to.deep.eq(['a', 'b', 'c'])
})
})
If you are still having trouble, Cypress applies the test context to callback functions, so you can use cy.state('ctx')
instead of this
, then there is no need to change the arrow functions to function()
// works with arrow function
Cypress.Commands.add('aliases', (aliasNames) => {
return aliasNames.map(a => cy.state('ctx')[a])
})
Note cy.state('ctx')
is an internal method.
Upvotes: 26
Reputation: 1114
this.* notation can be used to access multiple aliases within a single code block:
cy.wrap('foo').as('foo');
cy.wrap('bar').as('bar');
cy.wrap('baz').as('baz');
cy.then(function () {
cy.log(this.foo + this.bar + this.baz)
})
See this article for details
Upvotes: 9
Reputation: 9
This is similar to the values array used above but I do the following:
// Make all data available in one alias:
const testData = {};
cy.get('@data1').then((data1) => {
testData.data1 = data1;
});
cy.get('@data2').then((data2) => {
testData.data2 = data2;
});
cy.get('@data3').then((data3) => {
testData.data3 = data3;
});
cy.wrap(testData).as('testData');
Then when you need the data:
cy.get('@testData').then((testData) => {
const { data1, data2, data3 } = testData;
...
});
Upvotes: 0
Reputation: 1864
One different solution which is custom developed by Mr. Nicholas Boll, where you will get aliases as an array using custom commands createAlias/ getAliases
,
// get many aliases - API is similar to Promise.all
cy.getAliases([getFoo, getBar, getOne]).then(([foo, bar, one]) => {
foo // string
bar // string
one // number
console.log(foo, bar, one) // logs 'foo', 'bar', 1
})
Here is the complete details in his blog - https://medium.com/@NicholasBoll/cypress-io-making-aliases-type-safe-b6f5db07d580
Code reference - https://github.com/NicholasBoll/cypress-example-todomvc/tree/feat/type-safe-alias
Upvotes: 7
Reputation: 7302
You can do this:
it('test', () => {
cy.wrap('foo').as('foo');
cy.wrap('bar').as('bar');
cy.wrap('baz').as('baz');
const values = [];
cy.get('@foo').then( val => {
values.push(val);
return cy.get('@bar');
}).then( val => {
values.push(val);
return cy.get('@baz');
}).then( val => {
values.push(val);
someFunc(...values);
});
});
Or you can use this helper I cobbled together (put it in your 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;
}
and use it like so:
it('test', () => {
cy.wrap('one').as('one');
cy.wrap('two').as('two');
cy.wrap('three').as('three');
cy.all(
cy.get(`@one`),
cy.get(`@two`),
cy.get(`@three`)
).then( values => {
someFunc(...values);
});
});
Upvotes: 12