Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Misleading error message when trying to access (probably) detached DOM-Element #9176

Closed
pakaufmann opened this issue Nov 12, 2020 · 16 comments
Closed
Labels
pkg/driver This is due to an issue in the packages/driver directory type: bug

Comments

@pakaufmann
Copy link

Some of our tests sometimes showed the following error message: cy.contains() failed because it requires the subject be a global window object.

This wasn't very helpful at all, because the check looked something like this: cy.get("foo").contains("bar")

The cy.get("foo") obviously is not a window-object.

After digging around in the source code, I think the following line is the problem:

When all tests fail on the type, only the first error is shown, which in the "contain"-Case is the check if it is a window-object. It probably should show all errors, as then a user would also see the "cy.get("foo") is detached"-error. This would help in trying to debug applications which seem to fail at random.

@jennifer-shehane
Copy link
Member

Can you provide a reproducible example? We won't be able to open a PR to fix this without first writing a failing test that the PR fixes. Here are some tips for providing a Short, Self Contained, Correct, Example and our own Troubleshooting Cypress guide.

@jennifer-shehane jennifer-shehane added the stage: needs information Not enough info to reproduce the issue label Nov 16, 2020
@pakaufmann
Copy link
Author

pakaufmann commented Nov 16, 2020

This is the simplest example I could come up with:

Test:

describe('This test', () => {
  it('will fail with a confusing error message', () => {
    cy.visit('/page-1.html');
    const willFail = cy.get('#failing').click().contains('not attached');
  })
})

page-1.html:

<html>
<head>
</head>
<h1>Page 1</h1>
<div id="failing">not attached</div>
<script>
const el = document.getElementById('failing');

el.addEventListener('click', function(e) {
    el.remove();
});
</script>

</html>

The error message the test will output is CypressError: cy.contains() failed because it requires the subject be a global window object., instead of something like cy.contains() failed because the element was not attached to the DOM.

@jayarjo
Copy link

jayarjo commented Feb 2, 2021

This is still a problem.

@pakaufmann have you detected what was causing it? In my case it is not clear, 'cause DOM element is clearly on the page.

@jennifer-shehane
Copy link
Member

I can recreate the error from the provided code:

<html>
<h1>Page 1</h1>
<div id="failing">not attached</div>
<script>
  const el = document.getElementById('failing');

  el.addEventListener('click', function (e) {
    el.remove();
  });
</script>
</html>

spec.js

it('will fail with a confusing error message', () => {
  cy.visit('index.html')
  cy.get('#failing').click().contains('not attached')
})

Screen Shot 2021-02-03 at 9 34 40 AM

This is failing from this line in Cypress code: https://github.com/cypress-io/cypress/blob/develop/packages/driver/src/cy/ensures.js#L208:L208

@jennifer-shehane jennifer-shehane added stage: ready for work The issue is reproducible and in scope type: bug pkg/driver This is due to an issue in the packages/driver directory and removed stage: needs information Not enough info to reproduce the issue labels Feb 3, 2021
@pakaufmann
Copy link
Author

@jayarjo The "real" case was a bit more complicated, where we replaced one part of the page dynamically with a response from the server. So maybe you have the same problem, where you initialize the page, do something asynchronously and replace some DOM-elements with new ones? Then, if you hold onto a reference of the old (now detached) element you get the error, while in the browser it looks like everything is still there.

@manikantag
Copy link

manikantag commented Jun 23, 2021

@pakaufmann I've same problem and mine is just as you've described. Any workaround for this?

All I'm doing is checking if url contains a string after a click().

cy.contains('.ag-cell', 'Performance').click();   // <----- this will cause route change (using Angular, btw)
cy.url().contains('/performance');   // <----- this is not working

@manikantag
Copy link

Small update: said issue is coming when I'm asserting on URL. Instead, if I assert for some other text on the new page, it is working as expected.

Ex:

cy.contains('.ag-cell', 'Performance').click();   // <----- this will cause route change (using Angular, btw)
cy.contains('h1', 'Performance').should('exist');   // <----- this is working

@rogoit
Copy link
Contributor

rogoit commented Aug 6, 2021

Have the same problem

@cjkepinsky
Copy link

any workaround so far?

@svalluri-cais
Copy link

I have the same issue. May be will try to find an element of the page after redirection and then assert the url.

@MangalamGanesan
Copy link

I'm also facing same issue . But this doesn't happen every time. Sometime it works fine.

cy.get('#id').contains('##text##')

@Jai-Gogineni
Copy link

I faced same but with promise it works fine
cy.get(selectors) .invoke("text") .then((el) => { expect(el).contains(text); });

@steinybot
Copy link

steinybot commented Oct 10, 2022

The element doesn't necessarily need to be detached, it also happens with custom assertions:

    cy.get('.optional-element')
      .should(() => { })
      .contains('Cannot find me')

If none of these match then it fails with:

     CypressError: `cy.contains()` failed because it requires the subject be a global `window` object.

The subject received was:

  > `jQuery{0}`

The previous command that ran was:

  > `cy.should()`

All 3 subject validations failed on this subject.
      at ensureWindow (https://example.cypress.io/__cypress/runner/cypress_runner.js:147411:76)
      at validateType (https://example.cypress.io/__cypress/runner/cypress_runner.js:147226:16)
      at $Cy.ensureSubjectByType (https://example.cypress.io/__cypress/runner/cypress_runner.js:147256:9)
      at $Cy.pushSubject (https://example.cypress.io/__cypress/runner/cypress_runner.js:157699:12)
      at wrapped (https://example.cypress.io/__cypress/runner/cypress_runner.js:157188:19)
  From Your Spec Code:
      at Context.eval (webpack:///./cypress/e2e/spec.cy.js:9:7)
      ```

@BlueWinds
Copy link
Contributor

100% agree that our error messaging isn't super helpful when the subject doesn't match what we were expecting. I've rewritten most of these for Cypress 12, and this sort of thing should occur way less often. #24628 has those changes, and see #7306 for discussion around how we've restructured retrying commands.

@rogoit
Copy link
Contributor

rogoit commented Nov 17, 2022

.shadow saved my life and company...thx a lot for your passion and work!!

@cypress-bot
Copy link
Contributor

cypress-bot bot commented Dec 6, 2022

Released in 12.0.0.

This comment thread has been locked. If you are still experiencing this issue after upgrading to
Cypress v12.0.0, please open a new issue.

@cypress-bot cypress-bot bot removed the stage: ready for work The issue is reproducible and in scope label Dec 6, 2022
@cypress-bot cypress-bot bot locked as resolved and limited conversation to collaborators Dec 6, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
pkg/driver This is due to an issue in the packages/driver directory type: bug
Projects
None yet
Development

No branches or pull requests