The cypress.get(element)
function fails without waiting or retrying if the element is not visible on the page.
The cypress.get(element)
function should wait and find the dom element in the page or timeout after the default timeout if the element is not visible in the page.
Non-working code:
describe('Starts a chat conversation', () => {
describe('When visiting /chat ', () => {
it('creates a new chat and the the chat bot starts sending messages', () => {
cy.loginAs(clientWithMembership); // custom command that execute an http call
const url = getChatUrl();
cy.visit(url);
cy.get('div[data-cy=chat-message-container]').should('have.length', 1); // Fails without waiting
});
});
});
Working code: (adding a wait before checking if the element exists)
describe('Starts a chat conversation', () => {
describe('When visiting /chat ', () => {
it('creates a new chat and the the chat bot starts sending messages', () => {
cy.loginAs(clientWithMembership); // custom command that execute an http call
const url = getChatUrl();
cy.visit(url);
cy.wait(3000);
cy.get('div[data-cy=chat-message-container]').should('have.length', 1);
});
});
});
Cypress: 3.0.1
Mocha: 4.0.1
Browser: Chrome
Curious, does your test fail and return:
...failed because it requires a DOM element.
The subject received was:
> undefined
The assert fails with the message:
expected '' to have a length of 1 but got 0
@dan19 It does appear from the information provided that Cypress attempted to retry for the duration of the timeout (4000ms), and did not find the DOM selector to have a length of 1. Could you try increasing the timeout of the actual get
to see if this helps?
cy.get('div[data-cy=chat-message-container]', {timeout: 7000}).should('have.length', 1);
Also, make sure you are following some of our recommendations on waiting for you app to load before getting an element in your tests. https://on.cypress.io/using-cypress-faq#How-do-I-wait-for-my-application-to-load
@jennifer-shehane thanks for your answer. I've tried that already and it doesn't even wait a second when I passing in the timeout option.
Can you provide a screenshot and/or video
@brian-mann @jennifer-shehane I believe my issue has to do with the fact that when I go to /chat
then it redirects to /chat/create
and then /chat/<id>
. This is after this last redirection that the element would be available.
Do you think that is this issue and if so how to fix that?
I read the documentation but can not figure it out.
@dan19 Could you try a cy.visit()
directly to the /chat/<id>
url and see if it happens?
It seems like the challenge is waiting for /chat/<id>
despite an intermediate call to /chat/create
.
I'm curious if this would this work:
// Create a server to listen for route requests
cy.server();
// Create a route listener to try and catch `/chat/<id>`
cy.route("/chat/!(create)").as("userID");
// Visit entry point
cy.visit(url);
Wait for a response from '@userID'
cy.wait("@userID");
// Proceed to interact with the chat container
cy.get('div[data-cy=chat-message-container]').should('have.length', 1);
I'm new to Cypress and don't use negated globbing patterns very often, so I could be missing something. It should probably be refactored to specify the user route (pass the ID or use regex) avoid using the negation completely. That way, if create
ever changes or other intermediary calls are introduced, it won't fire off accidentally.
Even better might be to change your API to call /chat/user/<id>
or change the /chat/create/
or avoid the conflicts by using different HTTP methods.
Hey @dan19, did you find a solution to your issue?
I do have the the problem, its not waiting even a second and failing. Waiting for api response wont help if you have a long list of data to render. Api got 200 response but react takes time to render huge amount of data from response. Any suggestions how to wait until element is presented?
@mikhaildzarasovvineti If you want to purely wait for an element to be present on the page, you can increase the timeout that Cypress waits for an element to be present. cy.get('button', {timeout: 60000}
.
Unfortunately we have to close this issue due to inactivity. Please comment if there is new information to provide concerning the original issue and we can reopen.
I've run into something similar.. I simply prepend be.visible assertion and the timeout is applied.
i.e. cy.get('element').should('be.visible').and('some.assertion')
For me, upgrading to Cypress 4.4.0 caused this issue. I've found an answer on Stackoverflow to waitForAngular similar to Selenium: https://stackoverflow.com/a/58706928/883603
It fixed the element nog being present in the DOM when Cypress starts to assert for me.
I don't know if its the same issue, but i am confused about this behaviour:
A get with an empty result set:
cy.get('div.recipe[recipeid]:visible').should("have.length", 1)
results in:
and i would expect that this would fail.
@laDanz Please open a new issue with a fully reproducible example. This should have.
Most helpful comment
@dan19 It does appear from the information provided that Cypress attempted to retry for the duration of the timeout (4000ms), and did not find the DOM selector to have a length of 1. Could you try increasing the timeout of the actual
get
to see if this helps?Also, make sure you are following some of our recommendations on waiting for you app to load before getting an element in your tests. https://on.cypress.io/using-cypress-faq#How-do-I-wait-for-my-application-to-load