0

I have a test that need to download file from a web by clicking on a button.

Test is able to pass when in non-headless mode.

However when I run it in headless it fails with timeout to download file.

Here are some details:

  • Selenide version: 5.25.0
  • Chrome Driver version: 111.0.5563.64

My configurations:

  • non-headless run:
Configuration.timeout = 20000;
Configuration.fileDownload = FOLDER;
  • headless run:
Configuration.headless = true;
Configuration.timeout = 20000;
Configuration.fileDownload = FOLDER;

Other options are as default, like downloads folder build/downloads and rest of them.

My Selenide code to download file:

    @SneakyThrows
    public String downloadFile() {
        return downloadButton.download(10000, withExtension("pdf")).getAbsolutePath();
    }

The button element itself:

<button class="MuiButtonBase-root MuiButton-root MuiButton-contained MuiButton-containedSecondary" tabindex="0" type="button" test-id="download-button">
    <span class="MuiButton-label">Download</span>
    <span class="MuiTouchRipple-root"></span>
</button>

Logs:

  • non-headless:
13:20:09.959 INFO com.codeborne.selenide.impl.DownloadFileToFolder - Downloaded 1 files:
  #1  {root}\build\downloads\1678792759151_10256_1\109fc116-cc8b-42ba-9d7b-20733276bf64.pdf
  • headless:
13:07:19.760 INFO com.codeborne.selenide.impl.DownloadFileToFolder - Downloaded 0 files:
13:07:19.778 INFO com.codeborne.selenide.impl.WindowsCloser - File has been opened in a new window, let's close 1 new windows
13:07:19.778 INFO com.codeborne.selenide.impl.WindowsCloser - Let's close B0C0F608D49BC5C008986B2B7AB210C5

I've tried all of the solutions described in similar topics with adding a lot of different combinations of chrome options but no luck.

Any help appreciated!

Serhii Kachan
  • 345
  • 4
  • 13

1 Answers1

2

Well, I've found a reason.

Recently Chromium drivers changed their headless mode configs.

You can find more details in this answer: https://stackoverflow.com/a/73840130/11830541

Exactly my problem was that I used old Selenide version that uses the legacy --headless arg while creating headless options, however it must be --headless-new since Chrome 109.

To make this work with older versions of Selenide I used a workaround like this:

ChromeOptions options = new ChromeOptions();

options.addArguments("--headless=new");
options.addArguments("--disable-gpu");
options.addArguments("--disable-background-networking");
options.addArguments("--enable-features=NetworkService,NetworkServiceInProcess");
options.addArguments("--disable-background-timer-throttling");
options.addArguments("--disable-backgrounding-occluded-windows");
options.addArguments("--disable-breakpad");
options.addArguments("--disable-client-side-phishing-detection");
options.addArguments("--disable-component-extensions-with-background-pages");
options.addArguments("--disable-default-apps");
options.addArguments("--disable-features=TranslateUI,ChromePDF");
options.addArguments("--disable-hang-monitor");
options.addArguments("--disable-ipc-flooding-protection");
options.addArguments("--disable-popup-blocking");
options.addArguments("--disable-prompt-on-repost");
options.addArguments("--disable-renderer-backgrounding");
options.addArguments("--disable-sync");
options.addArguments("--force-color-profile=srgb");
options.addArguments("--metrics-recording-only");
options.addArguments("--no-first-run");
options.addArguments("--password-store=basic");
options.addArguments("--use-mock-keychain");
options.addArguments("--hide-scrollbars");
options.addArguments("--mute-audio");

Configuration.browserCapabilities = options;

Other options from --headless=new arg are the same that Selenide adds under-the-hood when you use Configuration.headless = true;

NOTE: It is better to upgrade Selenide dependency to newer version where this Chromium Driver change is handled properly: https://github.com/selenide/selenide/blob/main/CHANGELOG.md#6120-released-24022023

Serhii Kachan
  • 345
  • 4
  • 13