cypress-io / cypress

Fast, easy and reliable testing for anything that runs in a browser.
https://cypress.io
MIT License
47.02k stars 3.18k forks source link

Cypress fails to detect DOM elements - subject was 'undefined' #1631

Closed Gennadiii closed 6 years ago

Gennadiii commented 6 years ago

Bug

Current behavior:

This is a flaky bug with reproducibility about 5% CypressError: cy.click() failed because it requires a DOM element It might be cased by slow server response which might take up to 2 seconds. I tried cy.wait, .should('be.visible'), increasing default timeouts, setting timeout for the click, but nothing helps. Passed test: 2018-04-23 13_45_43-integration The same failed test: 2018-04-23 13_45_35-integration

The same sometimes happen to assertions: Passed test: 2018-04-23 13_45_07-integration Failed test: 2018-04-23 13_42_43-integration

Notice second example with assertion - failed test didn't click between 2 asserts. Although it is the same piece of code.

jennifer-shehane commented 6 years ago

Hey @Gennadiii, could you provide the test code for these cases? I am particularly wondering if you are using aliases or .as() in your querying of the element.

Gennadiii commented 6 years ago

@jennifer-shehane Nope, just cy.get().should() - cy.get().click()

jennifer-shehane commented 6 years ago

@Gennadiii We will need to be able to reproduce this situation on our end in order to look into what is causing the DOM element to wrongfully be undefined.

Can you provide an example of this that we can run on our end? Perhaps an example of the library you are using for the accordion (if applicable) or a repo with a smaller reproducible example?

Gennadiii commented 6 years ago

Unfortunately I can't provide an example. This issue reproduces with accordions, dropdowns and one link with svg inside.

brian-mann commented 6 years ago

@Gennadiii that would be the example code we are looking for. Something that is minimally reproducible. Without this we cannot do anything other than to wait until we see another user report the same problem or notice it ourselves. Having the issue open helps, but it will remain unsolved.

joelmeiller commented 6 years ago

Hi I have the same problem. We are using React and Meteor. The random behaviour as described above appears in my test runs too.

I am still working on it, but maybe I can provide you a test example in the next days.

Furthermore, I have the problem, that if the should assertion fails (because the element could not be found) the test runs forever.

MarkNewcomb1 commented 6 years ago

Same problem here. Here's my code - note the two cy.pause commands, one active and one commented out.

describe('testing for drill 2 hacker news', function(){
    it('1. Make sure the title has "Vue HN 2.0" in it 1. Make sure more than 1 news items show up on the page1. Go to the "New" area via the link1. Make sure you\'re on the correct page1. Make sure more than 1 items show up on the page1. Go to the next set of results with the "more" link1. Make sure you\'re on the correct page1. Make sure more than 1 news items show up on the page1. Go to the jobs page via the link1. Make sure you\'re on the correct page1. Make sure more than 1 news items show up on the page', function() {
        cy.visit('https://e2e-hackernews.herokuapp.com/')
        cy.get('title')
        .should('contain', 'Vue HN 2.0')
        cy.get('.news-item')
        .should('have.length.gt', 1)
        cy.get('a').contains('New')
        .click()
        cy.url()
        .should('contain', '/new')
        cy.get('body').find('.news-item')
        .should('have.length.gt', 1)
        //cy.wait(1000)
        //cy.pause()
        cy.get('a').contains('more >')
        cy.pause()
        .click()
        cy.url().should('include', '/new/2')
        cy.get('body').find('.news-item')
        .should('have.length.gt', 1)
        cy.get('a').contains('Jobs')
        .click()
        cy.url()
        .should('contain', '/job')
        cy.get('body').find('.news-item')
        .should('have.length.gt', 1)
    })
})

If you comment out the one that's active and un-comment the one that's currently commented, then step through the pauses, the tests will pass - but if you leave the code as I've pasted below, you'll get a

CypressError: cy.click() failed because it requires a DOM element.

The subject received was:

undefined

The previous command that ran was:

cy.pause()

Screenshot:

screen shot 2018-06-11 at 2 30 20 pm

I'm doing this for an assignment that specifically does not want us to use cy.wait (which, if I give .wait 1000 or 2000 milliseconds, does pass).

jennifer-shehane commented 6 years ago

@MarkNewcomb1 This actually looks to be an issue with the use of .pause() and .click() chained together. So .pause() yields the same subject that it was given, and .click() expects a DOM element to be chained off of, so writing cy.pause().click() is not the correct use of either of the commands.

Could you try writing:

cy.get('a').contains('more >')
  .pause()
  .click()

The above has the element found from the .contains('more >') yielded to .pause(). The element is then passed through .pause() to .click() to be clicked on.

MarkNewcomb1 commented 6 years ago

Ah, I see - that makes the pause work. Thank you.

jennifer-shehane commented 6 years ago

Hey @Gennadiii, just wanted to follow up.

Gennadiii commented 6 years ago

Hi @jennifer-shehane, There were no specific steps, the issue is flaky. Unfortunately I can't give you any code since I don't work for that project anymore.

marcelo-rebello commented 5 years ago

Similar problem... I am using a Quasar/Vue.js frontend. I had tried several combinations of cy.get().contains(), cy.get().should() or cy.contains()... no way to detect...

looks like Cypress have lots of trouble to work with modern SPA sites... Cypress 3.1.2 - windows 10

my code template is:

<template>
    <q-collapsible icon="explore" label="Notes" data-cy="icon">
        <q-input :value="value" :rows="rows" :stack-label="label"  @change="handleChange"
            type="textarea" data-cy="ClinicalNotes"  />
    </q-collapsible>
</template>

my test is:

it('Render/ Has UI elements', () => {
        cy.get('[data-cy=icon]').click() // open the colapsible/accordion
        cy.wait(3000) // no matter how it waits...
        cy.contains('Clinical value')  // you can see the text rendered in browser, but can not detect
    })

untitled

jennifer-shehane commented 5 years ago

Hey @marcelo-rebello, your failed test does not look related to the issue detailed here of the subject logging as undefined.

In terms of .contains() not finding the content, this can happen sometimes if there are new lines or space characters within the 'Clinical value'.

Also, are you trying to look at the text that is the value of an input?

marcelo-rebello commented 5 years ago

Well, if I do something like cy.contains('Clinical').should(...) I will have an undefined result logged as Cypress fails to find the input field... It happens with several input types using Vue.js/Quasar frameworks...

Look at the value field works, but it looks like a bug or limitation of Cypress that is not documented or made explicit anywhere. Cypress works on top of UI, but is not able to get a visible text element???

Maybe contains could have a configurable list of places to look for text/value... or just look in value fields also. Maybe comment about this restriction on docs...

jennifer-shehane commented 5 years ago

@marcelo-rebello .contains() does not current look at input value fields. You can open a new issue for support for this.

gtycherry commented 5 years ago

Hi @jennifer-shehane I met below error when using contains. screen shot 2019-03-06 at 10 33 14 am

could you please help to suggest why above usage met error? Thanks.

bahmutov commented 5 years ago

Split the long chain. After wait do a new “cy.contains ...”

Sent from my iPhone

On Mar 5, 2019, at 21:34, gtycherry notifications@github.com wrote:

Hi @jennifer-shehane I met below error when using contains.

could you please help to suggest what api i can use to assert there is one specific element visible on page? Thanks.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub, or mute the thread.