3

Ok, here is my situation:

On the website that I'm testing, A part of my tests include a table where user's can add or delete rows. I cannot control if the table will be empty or not, so I need to have conditionals (IF) to explore two scenarios: 1. The table is empty; 2. The table is not empty.

What I came up with is just to check if the first row of the table exists. If it does, do some tests and then proceed, and if it doesn't just skip the table and proceed to the next texts.

Of course, I CANT just try to do a cy.get on the first row, because if it doesnt find the element, it is going to fail the test, so I tried this:

             cy.get('body').then(($body) => {
                 if ($body.find('firstRowElement').length > 0,  {timeout: 60000}) { 
                    cy.log("Im Inside")
                    cy.get('firstRowElement').then(($grid) => {  
                        //Do all the tests I need if the first row exists..
                    )}
                 } 
             )}

BUT IT DOESNT WORK. Even when the table is empty, it still enters the IF (I can see the log "Im inside"). Then, of course, on the next line (already inside the IF) the test fails because it tries to do a cy.get on an element that does not exist (first row of an empty table). So, it seems simply that the IF statement is not working.

What am I doing wrong?

PS: I need the timeout because the table takes a few seconds to load. I tried moving the timeout to inside the .find (like this - if ($body.find('firstRowElement', {timeout: 60000}).length > 0) but its even worse. When it is like this, it simply doesn't wait and skip everything because the table wasn't loaded yet. I also don't want to use cy.wait

Anybody can help me?

I'm inclined to believe that there is some sort of conflict between .find and timeout.

Omkar C.
  • 727
  • 8
  • 21
  • 1
    Does this answer your question? [Cypress - if then functions](https://stackoverflow.com/questions/53448012/cypress-if-then-functions) – Brendan Jun 01 '20 at 21:07
  • It doesnt. The first reply suggests exactly what I am doing (and in my case it doesnt work) and second reply mentions that the guy is clicking the label instead of the checkbox. – Gabriel Costa Finkel Jun 01 '20 at 23:17
  • 1
    You could use [cypress-wait-until](https://www.npmjs.com/package/cypress-wait-until) –  Jun 02 '20 at 01:35
  • How do you think cypress-wait=until could be implemented in this case ? I tried the following: if (cy.waitUntil(() => body.find('div#profile-type-list tr:nth-child(1) > td:nth-child(4)'))) { but it doesnt do what I want. – Gabriel Costa Finkel Jun 03 '20 at 14:06
  • 1
    `if ($body.find('firstRowElement').length > 0, {timeout: 60000})` is weird - timeout options are usually applied to Cypress commands, but here it's in a vanilla JS `if()` expression. Were you trying to apply it to the jQuery expression? –  Jun 06 '20 at 08:46
  • 1
    I think that's the reason why you get inside the `if()` regardless of the value of `$body.find('firstRowElement').length`. The object containing the timeout is always truthy. –  Jun 06 '20 at 08:49
  • See [comma operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comma_Operator), ***The comma operator (,) evaluates each of its operands (from left to right) and returns the value of the last operand.*** –  Jun 06 '20 at 08:52

2 Answers2

0

You can try this approach, very bare bones but it gives you an idea on how to conditionally test something like that. They key element is to work with what you see. As suggested above you really want to have something like waitUntil for future reference in your project.

cy.get('parent element of matrix or body').then($body => {
 cy.waitUntil(() => cy.get('parent element of first row')
 .then($selector => $selector.is(':visible') === true), { timeout: 60000 })
 if ($body.find('first Row Element').is(':visible')) {
  cy.log('A row exists')
 } else {
  cy.log('A row doesnt exists')
 }
})   
0

If you want to conditionally test for an element without failing, the generally accepted approach is to use a jQuery expression (as you have done, but see my comment above about the timeout option thwarting that approach).

I assume because you apply a timeout that the table row may or may not eventually show up, and you will wait up to 60 seconds.

One approach to conditionally test but also make use of Cypress retry is to use the fail event, an example of which is here Assert that element is not actionable in Cypress.

It's recommended only to use on('fail') to debug, but is used in the Cypress own test - you should choose if you want to ignore the warning.

Something like

it('...', (done) => {

  cy.once('fail', () => {
    // Skipping if the command below fails (i.e first row does not exist)
    done();  // done tells the test it ends here
  });

  cy.get('firstRowElement', { timeout: 60000 }).then(($grid) => {
    // Do all the tests I need if the first row exists..
    done();
  )}

});