Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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);
        })
    })
like image 812
p4t Avatar asked Mar 22 '19 11:03

p4t


People also ask

What should I know about aliases in Cypress?

Note: all aliases are reset before each test. See the aliases guide for details. Alias names cannot match some reserved words. Some strings are not allowed as alias names since they are reserved words in Cypress. These words include: test, runnable, timeout, slow, skip, and inspect.

How do I access aliases in Cy?

Aliased variables are accessed via cy.get ('@user') syntax. Some commands are inherently asynchronous, so using a wrapper to access the variable ensures it is resolved before being used. See documentation Variables and Aliases and get.

Why can't I access aliased files synchronously in Cypress?

as is asynchronous Remember that Cypress commands are async, including.as (). Because of this you cannot synchronously access anything you have aliased. You must use other asynchronous commands such as.then () to access what you've aliased.

Is it possible to assign the return values of Cypress commands?

The patterns that are going to be discussed in this tutorial is going to be useful for you, even when you are not working with Cypress. It should be noted that you can’t assign or work with the return values of any Cypress command, rather when you are working with Cypress commands, the commands will be enequeued and they run asynchronously.


1 Answers

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);
    });
});
like image 88
dwelle Avatar answered Oct 25 '22 23:10

dwelle