Why is Cypress saying my element is detached after just running a get command?

We Are Going To Discuss About Why is Cypress saying my element is detached after just running a get command?. So lets Start this Javascript Article.

Why is Cypress saying my element is detached after just running a get command?

How to solve Why is Cypress saying my element is detached after just running a get command?

This could be bad advice, but can you try the following?
cy.findAllByRole('rowheader').eq(2).click({force: true})

Why is Cypress saying my element is detached after just running a get command?

This could be bad advice, but can you try the following?
cy.findAllByRole('rowheader').eq(2).click({force: true})

Solution 1

This could be bad advice, but can you try the following?

cy.findAllByRole('rowheader').eq(2).click({force: true})

Original Author Ε Г И І И О Of This Content

Solution 2

Without a reproducible example, it’s speculative, but try adding a guard before the click using Cypress.dom.isDetached

cy.findAllByRole('rowheader').eq(2)
  .should($el => {
    expect(Cypress.dom.isDetached($el)).to.eq(false)
  })   
  .click()

If the expect fails, then a prior line is causing the detach and cy.findAllByRole is not re-querying the element correctly.

If so you might be able to substitute a plain cy.get().


I also like @AntonyFuentesArtavia idea of using an alias, because the alias mechanism saves the original query and specifically requeries the DOM when it finds it’s subject is detached.

See my answer here

From the Cypress source

const resolveAlias = () => {
  // if this is a DOM element
  if ($dom.isElement(subject)) {
    let replayFrom = false

    const replay = () => {
      cy.replayCommandsFrom(command)

      // its important to return undefined
      // here else we trick cypress into thinking
      // we have a promise violation
      return undefined
    }

    // if we're missing any element
    // within our subject then filter out
    // anything not currently in the DOM
    if ($dom.isDetached(subject)) {
      subject = subject.filter((index, el) => $dom.isAttached(el))

      // if we have nothing left
      // just go replay the commands
      if (!subject.length) {
        return replay()
      }
    }

Original Author Fody Of This Content

Solution 3

The answer to your question is written in the error message that you got:

Timed out retrying: cy.click() failed because this element is detached
from the DOM.

Cypress requires elements be attached in the DOM to interact with
them.

The previous command that ran was:

cy.eq()

This DOM element likely became detached somewhere between the previous
and current command.

Getting this error means you’ve tried to interact with a “dead” DOM element – meaning it’s been detached or completely removed from the DOM.
So by the time, cypress is about to click the element eq() was either detached or removed from the DOM.

In modern JavaScript frameworks, DOM elements are regularly re-rendered – meaning that the old element is thrown away and a new one is put in its place. Because this happens so fast, it may appear as if nothing has visibly changed to the user. But if you are in the middle of executing test commands, it’s possible the element you’re interacting with has become “dead”. To deal with this situation you must:

  • Understand when your application re-renders
  • Re-query for newly added DOM elements
  • Guard Cypress from running commands until a specific condition is met

When we say guard, this usually means:

  • Writing an assertion
  • Waiting on an XHR

You can read more from cypress docs and from the official cypress blog.

Solution: Make sure your elements are loaded and visible first and then perform the click()

cy.findAllByRole('rowheader').eq(2).should('be.visible').click();

Original Author Alapan Das Of This Content

Solution 4

I’m running in the same issue, get the same error while running:

cy.get('<elementId>').should('be.visible').click();

I can see as the test runs that it finds the element (and highlights it), the assertion is validated and then somehow the .click() fails to find the element even though it is chained.

I found that adding a static wait before this line for a couple seconds addresses the issue, but I am not sure why I would need to do that and don’t really want to use a static wait.

There are no asynchronous tasks running so there is no way to do a dynamic wait.

Original Author Chris Coulon Of This Content

Conclusion

So This is all About This Tutorial. Hope This Tutorial Helped You. Thank You.

Also Read,

ittutorial team

I am an Information Technology Engineer. I have Completed my MCA And I have 4 Year Plus Experience, I am a web developer with knowledge of multiple back-end platforms Like PHP, Node.js, Python and frontend JavaScript frameworks Like Angular, React, and Vue.

Leave a Comment