4

A part of my test includes 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 find out if the table is empty or not.

I try to check if the first row of the table exists. If it does, do some tests and proceed, or if it doesn't just skip the table and proceed.

Of course, I can't just try to do a cy.get on the first row, because if it doesn't find the element it will fail the test.

Instead 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 does not work.

When the table is empty it still enters the if statement.

Then the test fails on the next line because of the cy.get() on an element that does not exist. It seems that the if statement is not working.

Timeout

I need the timeout because the table takes a few seconds to load.

I tried moving the timeout to inside the $body.find() but it simply doesn't wait and skips everything because the table wasn't loaded yet.

I also don't want to use cy.wait().

I believe that there is some sort of conflict between .find() and timeout.

Andreas Violaris
  • 2,465
  • 5
  • 13
  • 26
  • 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
  • 2
    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
  • 3
    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

3 Answers3

2

I had the same issue. I fixed it using the below

export function clickIfExist(element) {
cy.get('body').then((body) => {
cy.wait(5000).then(() => {
  if (body.find(element).length > 0) {
    cy.log('Element found, proceeding with test')
    cy.get(element).click()
  } else {
    cy.log('Element not found, skipping test')
  }
})
})
}
Raphael
  • 1,738
  • 2
  • 27
  • 47
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();
  )}

});