selenium: [πŸ› Bug]: Get download file in client

What happened?

i have dynamic grid env , was working with old implantation for support download ( - SE_OPTS=--downloads-path /home/seluser/Downloads ,etc) and it worked fine . now started to config new download way ( - SE_OPTS=--enable-managed-downloads true)

https://www.selenium.dev/documentation/grid/configuration/cli_options/#enabling-managed-downloads-by-the-node.

issue is after download file in browser during test, and run get for http://localhost:4444/session/my session id/se/files got an empty respond value like below .

{
  "value": {
    "names": [
    ]
  }
}

How can we reproduce the issue?

in node docker set environment : - SE_OPTS=--enable-managed-downloads true
in code set desired_capabilities=  "se:downloadsEnabled": "true"

Relevant log output

no error in log

Operating System

dynamic-grid docker

Selenium version

latest

What are the browser(s) and version(s) where you see this issue?

latest

What are the browser driver(s) and version(s) where you see this issue?

latest

Are you using Selenium Grid?

No response

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Comments: 37 (19 by maintainers)

Most upvoted comments

This is what I used:

[docker]
# Configs have a mapping between the Docker image to use and the capabilities that need to be matched to
# start a container with the given image.
configs = [
    "selenium/standalone-firefox:4.9.1-20230508", '{"browserName": "firefox", "platformName": "linux", "se:downloadsEnabled": true}',
    "selenium/standalone-chrome:4.9.1-20230508", '{"browserName": "chrome", "platformName": "linux", "se:downloadsEnabled": true}',
    "selenium/standalone-edge:4.9.1-20230508", '{"browserName": "MicrosoftEdge", "platformName": "linux", "se:downloadsEnabled": true}'
    ]

# URL for connecting to the docker daemon
# host.docker.internal works for macOS and Windows.
# Linux could use --net=host in the `docker run` instruction or 172.17.0.1 in the URI below.
# To have Docker listening through tcp on macOS, install socat and run the following command
# socat -4 TCP-LISTEN:2375,fork UNIX-CONNECT:/var/run/docker.sock
url = "http://127.0.0.1:2375"
# Docker image used for video recording
video-image = "selenium/video:ffmpeg-4.3.1-20230508"

# Uncomment the following section if you are running the node on a separate VM
# Fill out the placeholders with appropriate values
#[server]
#host = <ip-from-node-machine>
#port = <port-from-node-machine>

docker compose

# To execute this docker-compose yml file use `docker-compose -f docker-compose-v3-dynamic-grid.yml up`
# Add the `-d` flag at the end for detached execution
# To stop the execution, hit Ctrl+C, and then `docker-compose -f docker-compose-v3-dynamic-grid.yml down`
version: "3"
services:
  node-docker:
    image: selenium/node-docker:4.9.1-20230508
    volumes:
      - ./assets:/opt/selenium/assets
      - ./NodeDocker/config.toml:/opt/bin/config.toml
      - /var/run/docker.sock:/var/run/docker.sock
    depends_on:
      - selenium-hub
    environment:
      - SE_EVENT_BUS_HOST=selenium-hub
      - SE_EVENT_BUS_PUBLISH_PORT=4442
      - SE_EVENT_BUS_SUBSCRIBE_PORT=4443
      - SE_OPTS=--enable-managed-downloads true

  selenium-hub:
    image: selenium/hub:4.9.1-20230508
    container_name: selenium-hub
    ports:
      - "4442:4442"
      - "4443:4443"
      - "4444:4444"

Test

	void canListDownloadedFiles() throws InterruptedException, MalformedURLException {
		URL gridUrl = new URL(remoteUrl);
		ChromeOptions options = new ChromeOptions();
		options.setCapability("se:downloadsEnabled", true);
		RemoteWebDriver driver = new RemoteWebDriver(gridUrl, options);
		driver.get("https://www.selenium.dev/selenium/web/downloads/download.html");
		driver.findElement(By.id("file-1")).click();
		driver.findElement(By.id("file-2")).click();
		SessionId sessionId = driver.getSessionId();

		// Waiting for the file to be remotely downloaded
		TimeUnit.SECONDS.sleep(3);

		HttpRequest request = new HttpRequest(GET, String.format("/session/%s/se/files", sessionId));
		try (HttpClient client = HttpClient.Factory.createDefault().createClient(gridUrl)) {
			HttpResponse response = client.execute(request);
			Map<String, Object> jsonResponse = new Json().toType(string(response), Json.MAP_TYPE);
			@SuppressWarnings("unchecked")
			Map<String, Object> value = (Map<String, Object>) jsonResponse.get("value");
			@SuppressWarnings("unchecked")
			List<String> names = (List<String>) value.get("names");
			assertTrue(names.contains("file_1.txt"));
			assertTrue(names.contains("file_2.jpg"));
		} finally {
			driver.quit();
		}
	}

Hi,

Any news on this bug?

It was postponed in several versions. Will it be fixed in 3.14?

Thanks!

@titusfortner @diemol - I think we can go ahead and close this issue

I have tried using selenium 4.15.0, coupled with docker tag 4.15.0-20231102

Just for the sake of completeness, here’s the docker compose file

# To execute this docker-compose yml file use `docker-compose -f docker-compose-v3.yml up`
# Add the `-d` flag at the end for detached execution
# To stop the execution, hit Ctrl+C, and then `docker-compose -f docker-compose-v3.yml down`
version: "3"
services:
  chrome:
    image: selenium/node-chrome:4.15.0-20231102
    shm_size: 2gb
    depends_on:
      - selenium-hub
    environment:
      - SE_EVENT_BUS_HOST=selenium-hub
      - SE_EVENT_BUS_PUBLISH_PORT=4442
      - SE_EVENT_BUS_SUBSCRIBE_PORT=4443
      - SE_OPTS=--enable-managed-downloads true

  firefox:
    image: selenium/node-firefox:4.15.0-20231102
    shm_size: 2gb
    depends_on:
      - selenium-hub
    environment:
      - SE_EVENT_BUS_HOST=selenium-hub
      - SE_EVENT_BUS_PUBLISH_PORT=4442
      - SE_EVENT_BUS_SUBSCRIBE_PORT=4443
      - SE_OPTS=--enable-managed-downloads true

  selenium-hub:
    image: selenium/hub:4.15.0-20231102
    container_name: selenium-hub
    ports:
      - "4442:4442"
      - "4443:4443"
      - "4444:4444"
TestNG test running on Chrome
import org.openqa.selenium.By;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.json.Json;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.openqa.selenium.remote.SessionId;
import org.openqa.selenium.remote.http.HttpClient;
import org.openqa.selenium.remote.http.HttpMethod;
import org.openqa.selenium.remote.http.HttpRequest;
import org.openqa.selenium.remote.http.HttpResponse;
import org.testng.Assert;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import static org.openqa.selenium.remote.http.Contents.string;

public class SeleniumChromeTest {
    private RemoteWebDriver driver;

    @BeforeTest
    public void setup() throws MalformedURLException {
        String hubUrl = "http://localhost:4444";
        ChromeOptions options = new ChromeOptions();
        options.setEnableDownloads(true);
        driver = new RemoteWebDriver(new URL(hubUrl), options);
        driver.manage().window().maximize();
    }

    @Test
    public void testing() throws InterruptedException, MalformedURLException {
        driver.get("https://www.selenium.dev/selenium/web/downloads/download.html");
        driver.findElement(By.id("file-1")).click();
        driver.findElement(By.id("file-2")).click();
        SessionId sessionId = driver.getSessionId();
        System.out.println(sessionId);
        // // Waiting for the file to be remotely downloaded
        TimeUnit.SECONDS.sleep(3);

        HttpRequest request = new HttpRequest(HttpMethod.GET, String.format("/session/%s/se/files", sessionId));
        try (HttpClient client = HttpClient.Factory.createDefault()
                .createClient(new URL("http://localhost:4444/"))) {
            HttpResponse response = client.execute(request);
            Map<String, Object> jsonResponse = new Json().toType(string(response), Json.MAP_TYPE);
            @SuppressWarnings("unchecked")
            Map<String, Object> value = (Map<String, Object>) jsonResponse.get("value");
            @SuppressWarnings("unchecked")
            List<String> names = (List<String>) value.get("names");
            System.out.println(names);
            Assert.assertEquals(names.size(), 2, "Found 2 files downloaded");
        }
    }

    @AfterTest(alwaysRun = true)
    public void quit() {
        driver.quit();
    }
}
TestNG test running on Firefox
import org.openqa.selenium.By;
import org.openqa.selenium.firefox.FirefoxOptions;
import org.openqa.selenium.json.Json;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.openqa.selenium.remote.SessionId;
import org.openqa.selenium.remote.http.HttpClient;
import org.openqa.selenium.remote.http.HttpMethod;
import org.openqa.selenium.remote.http.HttpRequest;
import org.openqa.selenium.remote.http.HttpResponse;
import org.testng.Assert;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import static org.openqa.selenium.remote.http.Contents.string;

public class SeleniumFirefoxTest {
    private RemoteWebDriver driver;

    @BeforeTest
    public void setup() throws MalformedURLException {
        String hubUrl = "http://localhost:4444";
        FirefoxOptions options = new FirefoxOptions();
        options.setEnableDownloads(true);
        driver = new RemoteWebDriver(new URL(hubUrl), options);
        driver.manage().window().maximize();
    }

    @Test
    public void testing() throws InterruptedException, MalformedURLException {
        driver.get("https://www.selenium.dev/selenium/web/downloads/download.html");
        driver.findElement(By.id("file-1")).click();
        driver.findElement(By.id("file-2")).click();
        SessionId sessionId = driver.getSessionId();
        System.out.println(sessionId);
        // // Waiting for the file to be remotely downloaded
        TimeUnit.SECONDS.sleep(3);

        HttpRequest request = new HttpRequest(HttpMethod.GET, String.format("/session/%s/se/files", sessionId));
        try (HttpClient client = HttpClient.Factory.createDefault()
                .createClient(new URL("http://localhost:4444/"))) {
            HttpResponse response = client.execute(request);
            Map<String, Object> jsonResponse = new Json().toType(string(response), Json.MAP_TYPE);
            @SuppressWarnings("unchecked")
            Map<String, Object> value = (Map<String, Object>) jsonResponse.get("value");
            @SuppressWarnings("unchecked")
            List<String> names = (List<String>) value.get("names");
            System.out.println(names);
            Assert.assertEquals(names.size(), 2, "Found 2 files downloaded");
        }
    }

    @AfterTest(alwaysRun = true)
    public void quit() {
        driver.quit();
    }
}
  1. End of May.
  2. The download needs to be done through the session, whatever you do manually is separate, Selenium cannot notice any manual interactions.

We missed Dynamic Grid when we revamped the downloads feature. I just fixed it so it works out of the box in 4.10.0.

In the mean time, you can add manually the "se:downloadsEnabled": "true" capability to the stereotypes in the config.toml.

yes , only while session is active I get respond , if test/session is end then error is deferent (something like no session found )