-2

I am beyond confused by Cypress and its whole "chaining" thing. I have something like the following:

The logging message returns the correct message, but returning my value is undefined. What am I missing here? I don't actually want the log message, but it was the only way to get some insight into what was going on. If I replace the cy.log with a return, I get undefined.

 const getCardUniqueByTitle = (cardSearch: string) => {
   cy.get(".card-title")).each((cardTitle) => {
        if (cardTitle.text().indexOf(cardSearch) >= 0) {
          cy.wrap(cardTitle)
            .parents("find-parents-id-here"))
            .find("some field")
            .find("a field within")
            .invoke("text")
            .then((unique) => {
              cy.log(`The unique for ${cardSearch} is '${unique}'`).then(
                () => {
                  return unique;
                });
            });
        }
      });
    };

So in my test I have something like:

describe( "Get sums for enabled cards", () => {
  it("sum two cards values", () => {
    const card1 = getCardUniqueByTitle("foo");
    const card2 = getCardUniqueByTitle("bar");
    const total = String(parseInt(card1) + parseInt(card2));
    cy.get(".subtotal).invoke("text").should('eq', total);
  });
});
      
QEViking
  • 1
  • 1
  • Where do you expect the value to be returned **to**? – Quentin Jun 29 '22 at 13:15
  • Does this answer your question? [How to return the response from an asynchronous call](https://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-asynchronous-call) – Quentin Jun 29 '22 at 13:22
  • Also https://stackoverflow.com/questions/3820269/return-a-value-when-using-jquery-each – Quentin Jun 29 '22 at 13:23
  • @Quentin - So, the code needs to return only the unique value for the specific cards I am searching, so that they can be added together. So, I have a test, this is supposed to be a reusable function for other tests as well. – QEViking Jun 29 '22 at 13:28
  • Can you provide a snippet where you want to use this code? I think as it is there isn't enough context to figure out what you want to do with the returned value. – agoff Jun 29 '22 at 13:34
  • ```const unique_value1 = callFunction("first card search"); const unique_value2 = callFunction("second card search");```. So that I can then use the values of those calls for further verification. – QEViking Jun 29 '22 at 13:35
  • Is the code in the question the only code for `callFunction()`? If so, the question should be updated reflecting the entire function and the uses for it. – jjhelguero Jun 29 '22 at 14:55
  • @jjhelguero I believe I have updated it to be more clear. – QEViking Jun 29 '22 at 15:26

1 Answers1

1

You'll have to return each cy. chain to retrieve the text of the element. For your case it will be:

const getCardUniqueByTitle = (cardSearch: string) => {
   return cy.get(".card-title")).each((cardTitle) => {
        if (cardTitle.text().indexOf(cardSearch) >= 0) {
          return cy.wrap(cardTitle)
            .parents("find-parents-id-here"))
            .find("some field")
            .find("a field within")
            .invoke("text")
        }
   });
};

Alternatively, a different approach would be use .contains() in junction with an .alias()

describe( "Get sums for enabled cards", () => {
  it("sum two cards values", () => {
    cy.contains(".card-title", "foo")
      .invoke('text')
      .then(parseInt)
      .as('fooNum')
    cy.contains(".card-title", "bar")
      .invoke('text')
      .then(parseInt)
      .as('barNum')
    cy.get(".subtotal")
      .invoke("text")
      .then(parsInt)
      .as('subtotal')
      .then(function() {
        expect(this.fooNum + this.fooBar).to.eq(this.subtotal)
      }
  })
})
jjhelguero
  • 2,281
  • 5
  • 13
  • Also `if (cardTitle.text().indexOf(cardSearch) > 0) {` – Fody Jun 29 '22 at 19:35
  • So, your first bit of code is something I have tried, and I just get back "Object{5}". I cannot seem to access the actual value. I am so beyond confused as to why I can't just return the explicit value. Because, if I put a cy.log on a .then call after that .invoke, the value I want is there. I just don't understand why these "chainables" are the way they are. And the documentation for them is just not intuitive. Your second one is good, but since I cannot leverage the "alias" beyond the "chain" I can't reuse it. – QEViking Jun 30 '22 at 13:25