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

When including zepto library, zepto object is passed as remote jQuery instead of expected Cypress jQuery to use for chaining. #6529

Closed
luokuning opened this issue Feb 21, 2020 · 8 comments
Labels
pkg/driver This is due to an issue in the packages/driver directory stage: ready for work The issue is reproducible and in scope stale no activity on this issue for a long period type: bug

Comments

@luokuning
Copy link

I'm using cypress v4.0.2, and here is a snip of my test code:

cy.get('div[data-component-data-id=301602] h2:first')
  .should(($el) => {
    expect($el).to.have.text('dress')
  })

and cypress complains about the assertion:

CypressError: Timed out retrying: You attempted to make a chai-jQuery assertion on an object that is neither a DOM object or a jQuery object.

The chai-jQuery assertion you used was:

  > text

The invalid subject you asserted on was:

  > Object{3}

To use chai-jQuery assertions your subject must be valid.

This can sometimes happen if a previous assertion changed the subject.

So I have to change expect($el).to.have.text('dress') to expect($el[0]).to.have.text('dress'), then the complain dismissed and test passed.

I debug the assertion a bit, turns out $el[0] is also a jquery element.

I also print $el and $el[0] to the console:

image

Isn't cy.get equivalent to jquery $? Why should I have to get the first element from $el?

@jennifer-shehane
Copy link
Member

I can't recreate this. Please provide a full example of the HTML you are testing against. My test code below:

<!DOCTYPE html>
<html>
<body>
  <h2>dress</h2>
</body>
</html>
it('have text not exist', () => {
  // h2 doesn't even exist
  cy.get('h2')
    .should(($el) => {
      expect($el).to.have.text('dress')
    })
})

it('have text', () => {
  cy.visit('index.html')
  cy.get('h2')
    .should(($el) => {
      // assertion passes
      expect($el).to.have.text('dress')
    })
  cy.get('h2')
    .should(($el) => {
      // assertion fails
      expect($el).to.have.text('foo')
    })
})

Screen Shot 2020-02-24 at 3 06 31 PM

Unfortunately we have to close this issue as there is not enough information to reproduce the problem. This does not mean that your issue is not happening - it just means that we do not have a path to move forward.

Please comment in this issue with a reproducible example and we will reopen the issue. 🙏

@luokuning
Copy link
Author

Thanks for the reply. Here is my complete test code in cypress/integration/image.spec.js:

describe('image component', () => {
  beforeEach(() => {
    cy.viewport('iphone-x')

    cy.visit('http://159.65.226.122', {
      onBeforeLoad(win) {
        Object.defineProperty(win.navigator, 'userAgent', {
          value:
            'Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1',
        })
      },
    })
  })

  it.only('title display', () => {
    cy.get('div[data-component-data-id=302749] h2:first')
      .should($el => {
        expect($el).to.have.text('dress')
      })
  })
})

And some settings in cypress/support/index.js:

Cypress.on('uncaught:exception', () => {
  // returning false here prevents Cypress from
  // failing the test
  return false
})

I can confirm that the html in http://159.65.226.122 would cause CypressError:

image

@jennifer-shehane
Copy link
Member

@luokuning Please provide the fully HTML/CSS/JavaScript or a hosted application since we cannot visit http://159.65.226.122 to run your tests.

@luokuning
Copy link
Author

@jennifer-shehane Sorry for the inconvenient. Here is the minimize HTML:

<!DOCTYPE html>
<html lang="en">
<head>
    <title>test</title>
</head>
<body>

<div data-component-data-id="302749">
    <h2 class="mshe-text-left">dress</h2>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/zepto/1.2.0/zepto.min.js"></script>
</body>
</html>

And it turns out that when I comment the script tag which load zepto, everything works fine. How is this error related to the application script?

@jennifer-shehane
Copy link
Member

I am able to recreate this with the following code. I don't believe this is a regression (tested back to 3.4.1).

index.html

<!DOCTYPE html>
<html lang="en">
<body>
  <h2>dress</h2>
  // commenting out zepto script causes this to pass
  <script src="https://cdnjs.cloudflare.com/ajax/libs/zepto/1.2.0/zepto.min.js"></script>
</body>
</html>
it('title display', () => {
  cy.visit('index.html')
  cy.get('h2')
    .should($el => {
      expect($el).to.have.text('dress')
    })
})

$el Without zepto script

Screen Shot 2020-02-28 at 3 55 53 PM

$el With zepto script

Screen Shot 2020-02-28 at 3 56 09 PM

How is this error related to the application script?

I have no idea. Application scripts can kind of do anything in JavaScript and they are obviously doing something with the elements on the page that Cypress is not expecting.

@cypress-bot cypress-bot bot added the stage: needs investigating Someone from Cypress needs to look at this label Feb 28, 2020
@jennifer-shehane jennifer-shehane added type: bug stage: needs investigating Someone from Cypress needs to look at this and removed stage: needs investigating Someone from Cypress needs to look at this labels Feb 28, 2020
@jennifer-shehane jennifer-shehane changed the title should(callbackFn) passing invalid jquery element to callbackFn should(callbackFn) passing invalid jquery element to callbackFn with zepto library Feb 28, 2020
@jennifer-shehane
Copy link
Member

jennifer-shehane commented Jul 9, 2020

Another failing use case brought up in #7917

@Ayase-252 mentioned:

After digging into the code, I find that the problem may arise in there. The remoteJQuery is actually a Zepto. therefore, the remoteSubject is a zepto object with a jquery passing in.

Yes, this is how Cypress currently works. If cypress finds that the application under test (AUT) has a global jQuery instance, rather than wrap elements in cypress’s own jQuery, it will use the jQuery instance in the AUT which can have some surprising implications such as when the remote jQuery has been overwritten.

The reason this was originally designed this way was so that 3rd party jQuery plugins you’ve installed in your AUT would automatically be “accessible” and queryable from cypress’s API. So taking this behavior away would negate your ability to do this: cy.get('element').invoke('somePlugin', args).

But this is likely not a strong argument for keeping this behavior.

Whenever Cypress is using “global” functions on AUT instances/objects, the “global” functions cannot be trusted because they come from the AUT, which means they could have been replaced. A proposed solution is to always use top globals, but call them with the AUT window context, so that the user code this always functions correctly.

spec.js

it('test', () => {
  cy.visit('index.html')
  cy.get('body').then(($el) => {
    // `$el` is a zepto object now, the following will 
    // fail because $el is not a valid jQuery object
    cy.wrap($el).screenshot();
  });
})

index.html

<body>
  hello world
  <script src="https://cdnjs.cloudflare.com/ajax/libs/zepto/1.2.0/zepto.min.js"></script>
</body>

Screen Shot 2020-07-09 at 10 57 30 AM

@jennifer-shehane jennifer-shehane changed the title should(callbackFn) passing invalid jquery element to callbackFn with zepto library When including zepto library, zepto object is passed as remote jQuery instead of expected Cypress jQuery to use for chaining. Jul 9, 2020
@cypress-bot cypress-bot bot added stage: ready for work The issue is reproducible and in scope and removed stage: needs investigating Someone from Cypress needs to look at this labels Jul 9, 2020
@jennifer-shehane jennifer-shehane added the pkg/driver This is due to an issue in the packages/driver directory label Jul 9, 2020
@cypress-app-bot
Copy link
Collaborator

This issue has not had any activity in 180 days. Cypress evolves quickly and the reported behavior should be tested on the latest version of Cypress to verify the behavior is still occurring. It will be closed in 14 days if no updates are provided.

@cypress-app-bot cypress-app-bot added the stale no activity on this issue for a long period label May 17, 2023
@cypress-app-bot
Copy link
Collaborator

This issue has been closed due to inactivity.

@cypress-app-bot cypress-app-bot closed this as not planned Won't fix, can't repro, duplicate, stale Jun 2, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
pkg/driver This is due to an issue in the packages/driver directory stage: ready for work The issue is reproducible and in scope stale no activity on this issue for a long period type: bug
Projects
None yet
Development

No branches or pull requests

3 participants