cypress-io / cypress

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

Cannot download PDF file using Chrome with cypress run #27342

Open wongk opened 1 year ago

wongk commented 1 year ago

Current behavior

I am not sure if this is a bug or a feature request. When our app opens a PDF file using window.open, we would like for the file to be downloaded. By default, it is opened in a new tab. There is a setting in Chrome that configures this behavior, however, it doesn't seem to have any effect when using cypress run (headed or headless). It works fine when using cypress open.

When using cypress run, the file is opened in a new tab, and the test runner stops executing the test at that point. There is no error related to the file being opened. Instead, we receive a generic error that is described here: https://github.com/cypress-io/cypress/issues/5016.

I should also add that this used to work with our setup (GH Actions + Cypress Cloud) until recently. Downgrading the Cypress version didn't seem to fix it. Maybe it's related to the Chrome version?

Desired behavior

The file should be downloaded. Ideally, all files opened using window.open should be downloaded when running Cypress. I am not aware of a use case for opening the file in a new tab, and it seems to break the test runner as well.

Test code to reproduce

Click any element that causes window.open to execute (the _blank option may also be relevant).

Cypress Version

12.6.0

Node version

18.16.0

Operating System

multiple

Debug Logs

No response

Other

No response

nagash77 commented 1 year ago

@wongk In order to give our engineers the best chance at recreating your problem, please create a reproducible example using a fork of Cypress Test Tiny. This gives us the best chance of seeing exactly what you are seeing and being able to investigate effectively.

wongk commented 1 year ago

https://github.com/anthemiq/cypress-test-tiny

If you run the script via cypress open, the script runs successfully and the PDF file is downloaded (at least on my machine, I have Chrome configured to download PDF files).

If you run the script via npx cypress run --browser chrome --spec cypress/e2e/spec.cy.js, it says the script passes, however, the video indicates that the script simply stops running when the PDF file is opened. It is not downloaded.

joakim-sch commented 1 year ago

Having the exact same problem as @wongk ! Except, I have been able to downgrade Cypress to mitigate the problem. To me it seems that the problem was introduced in Cypress 12.15.0. I can run the script on 12.14.0 no problem, but on 12.15.0 or higher, the files is not downloaded and the script ends abruptly ending in the generic cy.screenshot() timeout

Browser: Chrome 115 (headless) Node Version: v18.17.0

joakim-sch commented 1 year ago

I found a workaround that worked for me. The problem definitely seems to be related to the new headless mode that was added to chrome in v112 (ref) and added support for in Cypress 12.15.0 (ref changelog).

The solution for me was simply to enable the old headless mode (ref) by adding this in my setupNodeEvents;

on('before:browser:launch', (browser, launchOptions) => {
        if (browser.name === 'chrome') {
          launchOptions.args.push('--headless=old')
          return launchOptions
        }
      })

Edit: I opened an issue with chromium about the issue in the new headless mode 🤞🏼 crbug link

wongk commented 1 year ago

Thank you @joakim-sch

joakim-sch commented 1 year ago

Latest update from chromium is that this is considered expected behaviour and will not be fixed 😞

Properko commented 11 months ago

I got it working this way (I know not ideal to make the test behavior differ from a real user's experience 😬, cypress way is to change the backend to support this) As a plus it downloads the file both in headless and headful modes.

// describe block

beforeEach(() =>
  cy.intercept(/.*\.pdf$/, (req) => {
    const pdfName = req.url.split("/").at(-1);
    console.log("Downloading pdf instead of opening in browser", {
      url: req.url,
      pdfName,
    });

    req.continue((res) => {
      res.headers["Content-Disposition"] = `attachment; filename=${pdfName};`;
    });
  })
);

// test to click a PDF link and verify downloaded file