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

Feature request: longer timeouts when network requests detected #6563

Closed
DamienCassou opened this issue Feb 26, 2020 · 5 comments
Closed

Feature request: longer timeouts when network requests detected #6563

DamienCassou opened this issue Feb 26, 2020 · 5 comments

Comments

@DamienCassou
Copy link

DamienCassou commented Feb 26, 2020

My server returns a mostly empty HTML page and then the client slowly populate the page by requesting more data through REST. I would like to write that kind of code:

cy.visit('/the/page');
cy.contains('some dynamic content');

The first line usually succeeds quite fast because the server doesn't have much to do. My problem is that the second line we often fail because cy.contains() only waits for defaultCommandTimeout even though there might be many requests after cy.visit() succeeds and before "some dynamic content" appears on the page.

I usually do something like this instead:

cy.server();
cy.route('/Data/').as('Data');

cy.visit('/the/page');

cy.wait('@Data');
cy.contains('some dynamic content');

This works better because cy.wait() waits much longer than cy.contains() before giving up. This gives plenty of time for "some dynamic content" to appear. I don't like this solution though because the test becomes more complex (it has more lines to understand) and more fragile (it depends on the client making a request to /Data).

I could increase the value of defaultCommandTimeout but this doesn't feel like a good solution because not all calls to cy.contains() should have a big timeout.

Would it be possible to make Cypress wait longer when network requests are detected? cy.wait() is quite clever about how it waits: it timesout after requestTimeout if no request were sent and after responseTimeout if at least one was sent. Maybe there could be a way to configure cy.contains() so it does something similar.

@CypressCecelia
Copy link
Contributor

Hi @DamienCassou! The command timeout can also be set for an individual command by passing {timeout: XXXX} as an option to cy.contains(). This way you would only extend the timeout for the commands that need it. Does this work for your situation? Here are the docs for what arguments can be passed.

@DamienCassou
Copy link
Author

That is another workaround we have used indeed. But it requires having a random number in the middle of the code base and it isn't as powerful as cy.wait() which stops after a small timeout if no request is sent from the client.

@CypressCecelia
Copy link
Contributor

CypressCecelia commented Feb 26, 2020

Could you provide more detail about why you feel cy.wait() is not a good solution in this case? If the network request needs to complete before moving on and checking for the existence of the element, using a cy.wait() for that request seems like it would make sense.

My thought with increasing the default timeout for cy.contains() when a network request is taking place is that it could result in increased timeouts when there are network calls that are unrelated. Using cy.wait() allows you to specify the exact request that needs to complete.

@DamienCassou
Copy link
Author

My code above with cy.wait() works perfectly. It's just that I feel these tests I'm concerned with shouldn't have to care about the requests the client does.

Maybe your solution to increase the timeout of cy.contains() is better. I can probably add a command cy.waitForDataAndCheckThePageContains() which is just a cy.contains() with an increased timeout. This command could also do a cy.wait() on any route (i.e., cy.route('*')). What do you think? Any suggestion for the command name? :-). I guess I would have to create another command for cy.get()

@jennifer-shehane
Copy link
Member

more fragile (it depends on the client making a request to /Data)

I would argue that using cy.route() with cy.wait() makes your tests much less fragile. You are testing required behavior of your application. This request has to finish before the data is present.

You will also receive a better error message. You will know:

    1. If the test fails because the request failed (now you know there's a bug with your XHR request).
    1. If the request passed and the content is not there (now you know there's another cause for the bug, that the request was successful, so it much has to do with the view layer of your app)

Yes, if you intend to use this set of commands over and over, like a general 'waitForPageToLoad', we would recommend writing a custom command to hold all these commands within.

Overall, you're likely looking for something along the lines of 'wait for network idle' feature outlined here: #1773

Duplicate of #1773

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants