You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Clicking anchor link to download file causes page load timeout #14857
changed the title [-]Cannot click button download in cypress 6.4.0[/-][+]Clicking anchor link to download file causes page load timeout[/+]on Feb 3, 2021
I am facing the same problem. Clicking on the Download button change window.location.href to download the file, also triggers the beforeunload event. We are downloading the file only, not redirecting towards a page actually, but for the redirection, cypress wait for a load event to be triggered by the application but as no redirection actually is happening it gets page load timeout error. I tried stopPropagation on "window:before:unload" event but didn't work. If we can invoke the load event during the wait or can execute the stopPropagation on the correct state it can be resolved I guess.
Hi, @jennifer-shehane I'm also facing the same issue even after updating Cypress 6.5.0. Clicking on a button downloads the file, but after downloading the file, the cypress waiting for page load which is not the expected behavior. please suggest a workaround for this problem.
Reacted by František Gič, dkusakina, Joe Kelly, A-ZC-Lau, mcopjan, Maurin-dev, Robin, Gerard, senedm, Thiago Moura and 1 more
What actually was happening in my case is that after clicking the download button a redirection was happening to download the file. From the application code: window.location.href was changing to download the file on click event. When cypress gets the redirection it waits for a page load event to get fired from AUT for continuing further. As no actual page redirection was happening so it got stuck and got page load timeout. So I tried the following workaround and it is working fine for my case:
Solution/Workaround:
All I needed was to fire a page load event to execute other cypress commands after clicking the download button rather than getting page load timeout. So before clicking the Download button or targeted file I added an event listener ‘click’ to listen out for the event and did something to trigger the page load event. Here is a tricky part, on event handling I triggered window.location.reload. But if I instantly trigger that on click event it will work but the file will not get downloaded. So I set a timeout of 5 sec, it may vary as per our requirement to download the file, after that, I am triggering window.document.location.reload(). This reloads the page and triggers a page load event. As soon as cypress get the page load event it continues executing further commands
Reacted by Matt Schreiner, dkusakina, Adrian Hernandez Lopez, Matt, Joe Kelly, Nazar Gandymov, Yaroslav Krivushenko, abhishekpatil173, Christopher Joslyn, vasal635 and 57 more
Reacted by Anastasiia, Recito Gigih P, mystic devx, Jonas Götz, adrianraszka, amitlenko, Bryan Arboleda, Anderson, mbwgh, Sanjay Makasana and 10 more
Reacted by adrianraszka, Bryan Arboleda, Anderson, mbwgh, Sanjay Makasana, Rojal Bati, Faith Berroya, Caitlin Boldt, gnoluv, Max-Antoine Clément and 5 more
Unfortunately, this doesn't seem to be enough. The test seems to succeed even if the file to be downloaded doesn't exist (404s etc.). You can confirm it by changing URL of the file to be downloaded:
I fixed it by intercepting the request and checking the status code of the response:
cy.window().document().then(function(doc){doc.addEventListener('click',()=>{setTimeout(function(){doc.location.reload()},5000)})/* Make sure the file exists */cy.intercept('/',(req)=>{req.reply((res)=>{expect(res.statusCode).to.equal(200);});});cy.get('[ng-click="vm.export()"]').click()})
Reacted by Joe Kelly, Nazar Gandymov, Ivan Pylyp, AJKarikari, A-ZC-Lau, Samuel Lucas, Renato O. Nunes, Luana, jayankamdar, Brayden Beavis and 9 more
Reacted by suseendranm
Reacted by Abhi D and Chung Kang
Reacted by Abhi D, Nyi Nyi Phyo, Sanjay Makasana, Chung Kang and Justin Clift
Reacted by Samuel Lucas, Renato O. Nunes, Abhi D, Chung Kang and Angelika
What actually was happening in my case is that after clicking the download button a redirection was happening to download the file. From the application code: window.location.href was changing to download the file on click event. When cypress gets the redirection it waits for a page load event to get fired from AUT for continuing further. As no actual page redirection was happening so it got stuck and got page load timeout. So I tried the following workaround and it is working fine for my case:
Solution/Workaround:
All I needed was to fire a page load event to execute other cypress commands after clicking the download button rather than getting page load timeout. So before clicking the Download button or targeted file I added an event listener ‘click’ to listen out for the event and did something to trigger the page load event. Here is a tricky part, on event handling I triggered window.location.reload. But if I instantly trigger that on click event it will work but the file will not get downloaded. So I set a timeout of 5 sec, it may vary as per our requirement to download the file, after that, I am triggering window.document.location.reload(). This reloads the page and triggers a page load event. As soon as cypress get the page load event it continues executing further commands
ng-click="vm.export()" is just a selector. It clicks the first(?) element with attribute ng-click="vm.export()". So, for example if I had this in HTML:
then the mentioned line would find this element and click it. If your link/button has id my-button then you would replace it with something like cy.get('#my-button').click()
I do understand it's a problem, but for the people asking for a fix or a patch, I'd like to hear how you would see this working. Cypress simply relies on a load event that never comes in this case and if it wouldn't do that, it would impact the 99,9% of the cases where they use it for stability.
They have the downloadfile method you can use.
Really consider what you're actually testing and what you expect
If you know the path to the file, it's simple. Use the downloadfile method, because elseway you're simply testing browser functionality.
If you don't know the path to the file, you can use multiple workarounds. For example, I change the headers to show content on the screen (and therefore have no issue with the load event). That works well for content that can be shown in the browser (like CSV). I posted that in this issue.
Another way is validating that the content contains something you expect. f.e. that it's a docx. by using a cy.get
For anyone who cannot afford page reloads in the middle of a test, I used the following to catch the error and continue.
Cypress.on("uncaught:exception",(error)=>{if(error.message.includes("Timed out after waiting `5000ms` for your remote page to load",)){returnfalse;}});Cypress.on("fail",(error)=>{if(error.message.includes("Timed out after waiting `5000ms` for your remote page to load",)){returnfalse;}throwerror;});
The timeout 5000ms which is different from the default timeout was set within the test with the following and is being reset later down the test.
Cypress.config("pageLoadTimeout",5000);
Hacky... but worked for me
It's not work because it never goes to uncaught:exception and if we return false on fail event, the test will pass.
I spent a long time investigating this. Cypress sets up listeners for page "stability" in a beforeunload handler. beforeunload fires when a form is submitted, but if the form doesn't result in a page load (e.g. because the response has a Content-Disposition: attachment header), then Cypress hangs.
Step 10 covers handling of Content-Disposition: attachment responses. Compare to...
Step 11, which is a normal navigation that loads a document and causes the "load" event to fire (see e.g. this for content-type: text/html). There is no navigation from a download in step 10. This is what Cypress got wrong.
This is the most reliable solution I came up with and the same logic I think Cypress should have in its core:
// in your commands.mjs fileCypress.Commands.add("suppressWaitForPageLoad",function(){cy.intercept("*",req=>{req.on("before:response",res=>{constisDownload=res.headers["content-disposition"]?.startsWith("attachment");// Need to exclude requests not made by the application, such as// background browser requests.constorigin=cy.getRemoteLocation("origin");constisFromAUT=req.headers["referer"]?.startsWith(origin);if(isDownload&&isFromAUT){Cypress.log({name: "suppressWaitForPageLoad",message: "Bypassing wait for page load event because response has Content-Disposition: attachment"});cy.isStable(true,"load");}});});});
@zbjornson, that seems like very good research and a nice solution! Is the cy.isStable(true, "load") another custom function?
I haven't tested it (and simply wanted to acknowledge the effort you put into the issue), but I can imagine that if people want to use this, it could be beneficial to add a check after the download. For example, that the file is fully downloaded). Also I'd go for adding a parameter for the path specifically (instead of the *) to limit the the risk of side-effects. That also helps in adding a unique alias and if you add an alias, you probably can also wait for the request to finish.
I do understand it's a problem, but for the people asking for a fix or a patch, I'd like to hear how you would see this working. Cypress simply relies on a load event that never comes in this case and if it wouldn't do that, it would impact the 99,9% of the cases where they use it for stability.
They have the downloadfile method you can use.
Really consider what you're actually testing and what you expect
If you know the path to the file, it's simple. Use the downloadfile method, because elseway you're simply testing browser functionality. If you don't know the path to the file, you can use multiple workarounds. For example, I change the headers to show content on the screen (and therefore have no issue with the load event). That works well for content that can be shown in the browser (like CSV). I posted that in this issue. Another way is validating that the content contains something you expect. f.e. that it's a docx. by using a cy.get
I think that is enough to test and I'd be curious what you want to test with Cypress on a downloaded file anyway.
@gvaatstra
I think you probably would agree all the workarounds mentioned are not prefect.
For example,
If the webpage's state is updated by user actions which are not yet permanently saved. A reload call could destroy all the progress and force the test to redo all the actions before continue the tests
Displaying files instead of downloading can only be applied to limited file types. Also, once displayed, a new tab is created and there is nothing we can do to get back to the old page unless we hack it with chrome-remote-interface
We may also want to E2ely test the file content if they are dramatically generated so checking the url in html is not sufficient
...
I think a good first step is to just add a flag to bypass the "load" check globally and advanced test writers can decide when and how to (dis)able it. We dont need it to be prefect, we just need a way to get stuff done
I don't know if this has been said before by someone else but if you're sure that you're clicking on a download link, you can workaround the issue by adding the download attribute to the html element before clicking it:
Activity
jennifer-shehane commentedon Feb 3, 2021
I can recreate this error with the test code below:
[-]Cannot click button download in cypress 6.4.0[/-][+]Clicking anchor link to download file causes page load timeout[/+]sarja510 commentedon Feb 18, 2021
I am facing the same problem. Clicking on the Download button change window.location.href to download the file, also triggers the beforeunload event. We are downloading the file only, not redirecting towards a page actually, but for the redirection, cypress wait for a load event to be triggered by the application but as no redirection actually is happening it gets page load timeout error. I tried stopPropagation on "window:before:unload" event but didn't work. If we can invoke the load event during the wait or can execute the stopPropagation on the correct state it can be resolved I guess.
Cypress version: 6.5.0
OS : Windows 10
kiransurakanti commentedon Feb 22, 2021
Hi, @jennifer-shehane I'm also facing the same issue even after updating Cypress 6.5.0. Clicking on a button downloads the file, but after downloading the file, the cypress waiting for page load which is not the expected behavior. please suggest a workaround for this problem.
sarja510 commentedon Feb 25, 2021
I got a workaround with the following issue,
What actually was happening in my case is that after clicking the download button a redirection was happening to download the file. From the application code: window.location.href was changing to download the file on click event. When cypress gets the redirection it waits for a page load event to get fired from AUT for continuing further. As no actual page redirection was happening so it got stuck and got page load timeout. So I tried the following workaround and it is working fine for my case:
Solution/Workaround:
All I needed was to fire a page load event to execute other cypress commands after clicking the download button rather than getting page load timeout. So before clicking the Download button or targeted file I added an event listener ‘click’ to listen out for the event and did something to trigger the page load event. Here is a tricky part, on event handling I triggered window.location.reload. But if I instantly trigger that on click event it will work but the file will not get downloaded. So I set a timeout of 5 sec, it may vary as per our requirement to download the file, after that, I am triggering window.document.location.reload(). This reloads the page and triggers a page load event. As soon as cypress get the page load event it continues executing further commands
the following solution worked for me fine:
I hope cypress will give a proper solution for this case, till then anyone can use this workaround. @jennifer-shehane @hiatien19 @kiransurakanti
AdrianHL commentedon Mar 2, 2021
I'm experiencing the same issue here. The solution proposed by @sarja510 works until a new version fix it.
mklepaczewski commentedon Mar 4, 2021
Unfortunately, this doesn't seem to be enough. The test seems to succeed even if the file to be downloaded doesn't exist (404s etc.). You can confirm it by changing URL of the file to be downloaded:
I fixed it by intercepting the request and checking the status code of the response:
JoeKellyFR commentedon Mar 15, 2021
@mklepaczewski This solution worked for me, thanks, and also to @sarja510 for the original approach. huge relief to be unblocked!
swatiamberkar commentedon Mar 18, 2021
@jennifer-shehane
@sarja510 This solution is worked for me.Thank You.
shilpajain09 commentedon Mar 31, 2021
This might be a very stupid question, but can you please let me know what is this doing
cy.get('[ng-click="vm.export()"]').click()
@mklepaczewski
mklepaczewski commentedon Mar 31, 2021
ng-click="vm.export()"is just a selector. It clicks the first(?) element with attributeng-click="vm.export()". So, for example if I had this in HTML:then the mentioned line would find this element and click it. If your link/button has id
my-buttonthen you would replace it with something likecy.get('#my-button').click()shilpajain09 commentedon Mar 31, 2021
@mklepaczewski thanks a lot for your prompt response.
Are we verifying somewhere that the file is downloaded successfully?
42 remaining items
gvaatstra commentedon Mar 9, 2023
I do understand it's a problem, but for the people asking for a fix or a patch, I'd like to hear how you would see this working. Cypress simply relies on a load event that never comes in this case and if it wouldn't do that, it would impact the 99,9% of the cases where they use it for stability.
If you know the path to the file, it's simple. Use the downloadfile method, because elseway you're simply testing browser functionality.
If you don't know the path to the file, you can use multiple workarounds. For example, I change the headers to show content on the screen (and therefore have no issue with the load event). That works well for content that can be shown in the browser (like CSV). I posted that in this issue.
Another way is validating that the content contains something you expect. f.e. that it's a docx. by using a cy.get
I think that is enough to test and I'd be curious what you want to test with Cypress on a downloaded file anyway.
ntvinhit commentedon Mar 22, 2023
It's not work because it never goes to
uncaught:exceptionand if we returnfalseonfailevent, the test will pass.zbjornson commentedon Apr 18, 2023
I spent a long time investigating this. Cypress sets up listeners for page "stability" in a
beforeunloadhandler.beforeunloadfires when a form is submitted, but if the form doesn't result in a page load (e.g. because the response has aContent-Disposition: attachmentheader), then Cypress hangs.These are the relevant parts of the HTML spec
Content-Disposition: attachmentresponses. Compare to...This is the most reliable solution I came up with and the same logic I think Cypress should have in its core:
Then use it like:
Firing a synthetic "load" event as shown in the post above can cause other issues. A page is only ever supposed to have one "load" event fired.
gvaatstra commentedon Apr 18, 2023
@zbjornson, that seems like very good research and a nice solution! Is the
cy.isStable(true, "load")another custom function?I haven't tested it (and simply wanted to acknowledge the effort you put into the issue), but I can imagine that if people want to use this, it could be beneficial to add a check after the download. For example, that the file is fully downloaded). Also I'd go for adding a parameter for the path specifically (instead of the *) to limit the the risk of side-effects. That also helps in adding a unique alias and if you add an alias, you probably can also wait for the request to finish.
SwPeter123 commentedon May 11, 2023
@gvaatstra
I think you probably would agree all the workarounds mentioned are not prefect.
For example,
I think a good first step is to just add a flag to bypass the "load" check globally and advanced test writers can decide when and how to (dis)able it. We dont need it to be prefect, we just need a way to get stuff done
Brugui7 commentedon Oct 31, 2023
I don't know if this has been said before by someone else but if you're sure that you're clicking on a download link, you can workaround the issue by adding the download attribute to the html element before clicking it:
That way the browser won't trigger the page change event and Cypress won't wait for a loadPage event.
fix: handle page loads when download is triggered #14857
cypress-bot commentedon Nov 8, 2023
Released in
13.5.0.This comment thread has been locked. If you are still experiencing this issue after upgrading to
Cypress v13.5.0, please open a new issue.