Search code examples
integration-testingcypress

How to get values of multiple aliases without introducing callback hell in Cypress?


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);
        })
    })

Solution

  • 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);
        });
    });