bucky barns
bucky barns

Reputation: 393

Cypress how to store values yielded by a function into a variable

This has been bugging me from a long time. I am not well versed with javascript. Here it goes:

  1. How do i store return value of a function into a variable:

    lenValue = cy.get(selector).children().length

Above line of code returns undefined But when i try following in cypress test runner console then I get a valid output:

cy.$$(selector).children().length --> gives me correct number
  1. How to return value from inside a then function and catch it to reuse later:

file1.js

function a(selector, attrName){
cy.get(selector).then(function ($el){
return $el.attr(attrName));
}

file2.js

state = file1Obj.a('#name','name')

Upvotes: 1

Views: 4765

Answers (3)

user14783414
user14783414

Reputation:

@aeischeid shows you the wrong way to do it.

His code works only for a static site, but web pages are rarely static. As soon as API fetches are involved, lucky timing goes out the window and the test bombs.

This is why Cypress commands have automatic retry. Otherwise we could just build tests with jQuery.


Since cy.$$(selector).children().length --> gives me correct number, use that inside the helper function.

function a(selector, attrName) {
  return cy.$$(selector).attr(attrName);      // jQuery methods used
}

Or

function a(selector, attrName) {
  return Cypress.$(selector).attr(attrName);  // jQuery methods used
}

But be aware that jQuery only handles static pages, it does not retry if the attribute that you want to query arrives slowly.

For that use a command

cy.get('#name')
  .should('have.attr', 'name')     // retries until name exists
  .then(name => {                  // guaranteed to have a value
    // use name here
  })

Upvotes: 2

aeischeid
aeischeid

Reputation: 576

Here is a example from a cypress test I have that seems pretty relevant

    let oldDescription;
    cy.get('input#description').should(($input) => {
      oldDescription = $input.val();
    });
    let randomDescription = Math.random().toString(36).substring(7);
    cy.get('input#description').clear().type(randomDescription);
    cy.get('input#description')
      .parents('.ant-table-row')
      .contains('Save').click();

    cy.get('input#description').should('not.exist');
    cy.contains(`${randomDescription}`);
    cy.contains(`${oldDescription}`).should('not.exist');

because oldDescription is set inside of an asyncronous callback it isn't safe to expect it to be set, farther down the code outside of that callback, but in a lot of cases with cypress you end up having some other .get call or thing that waits, effectively pausing the code long enough that you can get away with not worrying about it.

Upvotes: 1

sesamechicken
sesamechicken

Reputation: 1981

What you're doing makes complete sense, but simply put, you cannot. (per the docs). https://docs.cypress.io/guides/core-concepts/variables-and-aliases/#Return-Values

You can, however, use aliases to accomplish what (I think) you're after.
https://docs.cypress.io/guides/core-concepts/variables-and-aliases/#Aliases

Upvotes: 3

Related Questions