Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to check if element is never visible in Cypress e2e testing?

Is there any way to assert that an element is never visible at any point when routing within Cypress?

I have a server-rendered web app that is sometimes showing a "loading" state when it shouldn't. So when I navigate between pages, a "loading" indicator is showing for a few seconds and then disappearing.

I know that Cypress's assertions will sometimes "wait" -- in this case Cypress waits until loading indicator goes away and that makes the test think that it has passed. But I want the test to fail because the loading indicator was visible at some point.

I'm using these two assertions:

cy.get('[data-test="loading"]').should('not.exist');

cy.get('[data-test="loading"]').should('not.be.visible');

But both of them are passing because the loading indicator goes away.

I've checked through all the documentation but there doesn't seem to be some kind of method for checking that an element is never visible. Is there some method I'm missing or some hack to test this a different way?

like image 460
greatbearshark Avatar asked Dec 12 '18 15:12

greatbearshark


2 Answers

I might be crazy, and i have not tested this yet, but I wanted to throw this out there

I assume you are testing that there should NEVER be a loading indicator and it is waiting the default 4 seconds and the indicator goes away, and thus your test pass. So below I set the wait to zero, so it does not wait. I am also confused as to why you don't fix the actual code so you don't see the indicator if you are not supposed to. Perhaps you don't have access to the code..

cy.get('[data-test="loading"]',{ timeout: 0 }).should('not.exist');

cy.get('[data-test="loading"]',{ timeout: 0 }).should('not.be.visible');
like image 162
Maccurt Avatar answered Nov 12 '22 05:11

Maccurt


Cypress has a lite version of jQuery, so we can watch for changes to the parent of the element that should not exist.

@Maccurt's tests are applied whenever a change occurs.

You want to keep watch firing to a minimum, so find the immediate (or nearest) parent of tested element.

Note this covers exists tests, but should not be necessary for visible tests if the element is present all the time but is just not visible.


In this example a button is added to body.
The first test watches for a span (which is never added so the test succeeds).
The 2nd test watches for the button and fails.

describe('watching for an element to not appear', () => {

  const watchAndTest = function(parentSelector, assert) {
    Cypress.$(parentSelector).bind('DOMNodeInserted', function(event) {
      assert()
    });
  }

  it('should succeed because "span" does not exist', () => {
    const parentSelector = 'body'
    const watchForSelector = 'span'
    watchAndTest(parentSelector, 
      () => {
        // Place your 'assert' code here
        cy.get(`${parentSelector} ${watchForSelector}`,{ timeout: 0 })
          .should('not.exist');
      }
    )

    // Place your 'act' code here
    cy.get(parentSelector).then(parent => {
      var newElement = document.createElement('button');
      parent[0].appendChild(newElement)
    })
    Cypress.$(parentSelector).unbind('DOMNodeInserted')
  })

  it('should fail because "button" exists', () => {
    const parentSelector = 'body'
    const watchForSelector = 'button'
    watchAndTest(parentSelector, 
      () => {
        // Place your 'assert' code here
        cy.get(`${parentSelector} ${watchForSelector}`,{ timeout: 0 })
          .should('not.exist');
      }
    )

    // Place your 'act' code here
    cy.get(parentSelector).then(parent => {
      var newElement = document.createElement('button');
      parent[0].appendChild(newElement)
    })
    Cypress.$(parentSelector).unbind('DOMNodeInserted')
  })

})
like image 23
Richard Matsen Avatar answered Nov 12 '22 06:11

Richard Matsen