-
-
Notifications
You must be signed in to change notification settings - Fork 8.6k
Description
What happened?
When using Selenium Standalone with the Testcontainers GenericContainer for the Chrome driver, the following issue occurs when trying to use the Augmenter class to enable the BiDi protocol:
The Selenium Standalone container starts correctly, and I am able to access the WebDriver via http://localhost:4444.
However, when I attempt to augment the driver using new Augmenter().augment(driver);, the connection fails with a java.net.ConnectException, indicating that the WebDriver cannot connect to the BiDi WebSocket server, despite being able to access the same URL (http://localhost:4444) from within the container.
This issue occurs only when using Selenium Standalone and does not appear when Selenium Grid is used with the same Augmenter setup.
The connection failure does not occur when bypassing the Augmenter or using other WebDriver methods, but the BiDi functionality is unavailable in this case
How can we reproduce the issue?
Code to Reproduce -
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.openqa.selenium.remote.Augmenter;
import org.testcontainers.containers.GenericContainer;
import org.testng.annotations.Test;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.concurrent.TimeUnit;
import static org.testcontainers.shaded.org.awaitility.Awaitility.await;
public class SeleniumTestWithWebSockets {
@Test
public void testBiDiConnection() throws Exception {
// Start Selenium container
System.setProperty("webdriver.http.factory", "jdk-http-client");
// Start Selenium container
try (GenericContainer<?> seleniumContainer = new GenericContainer<>("selenium/standalone-chromium:4.25")
.withExposedPorts(4444)
.withEnv("SE_NODE_GRID_URL", "http://localhost:4444")
.withCreateContainerCmdModifier(cmd ->
cmd.getHostConfig().withShmSize(2147483648L))) { // Increase shared memory
seleniumContainer.start();
// Get Selenium URL
String seleniumUrl = "http://localhost:" + seleniumContainer.getMappedPort(4444);
// Wait for Selenium server readiness
await().atMost(30, TimeUnit.SECONDS).until(() -> {
try {
HttpURLConnection connection = (HttpURLConnection) new URL(seleniumUrl + "/status").openConnection();
connection.setRequestMethod("GET");
connection.connect();
return connection.getResponseCode() == 200;
} catch (Exception e) {
return false;
}
});
System.out.println("Container Logs: " + seleniumContainer.getLogs());
// Configure ChromeOptions
ChromeOptions options = new ChromeOptions();
options.setCapability("se:cdp", true); // Enable WebSocket-based BiDi commands
options.setExperimentalOption("w3c", true);
options.setCapability("webSocketUrl", true);
// Create WebDriver
WebDriver driver = new RemoteWebDriver(new URL(seleniumUrl), options);
driver = new Augmenter().augment(driver);
// Perform a simple test
driver.get("https://example.com");
System.out.println("Page Title: " + driver.getTitle());
// Quit WebDriver
driver.quit();
}
}
}
Dependencies -
org.testcontainers - 1.17.5 (tried with 1.20 as well)
org.seleniumhq.selenium - 4.25.0
org.awaitility - 4.2.2
Pom looks like -
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>testcontainer</artifactId>
<version>1.0-SNAPSHOT</version>
<name>Archetype - testcontainer</name>
<url>http://maven.apache.org</url>
<dependencies>
<!-- Testcontainers Selenium -->
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>selenium</artifactId>
<version>1.17.5</version> <!-- Or latest version -->
</dependency>
<!-- Selenium WebDriver -->
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>4.25.0</version> <!-- Ensure you use a version that supports BiDi -->
</dependency>
<!-- https://mvnrepository.com/artifact/org.awaitility/awaitility -->
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
<version>4.2.2</version>
<scope>test</scope>
</dependency>
<!-- JUnit for testing -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.7.0</version> <!-- Or any compatible version -->
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>RELEASE</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>Relevant log output
Container Logs: 2024-12-17 15:00:17,542 INFO Included extra file "/etc/supervisor/conf.d/chrome-cleanup.conf" during parsing
2024-12-17 15:00:17,543 INFO Included extra file "/etc/supervisor/conf.d/selenium.conf" during parsing
2024-12-17 15:00:17,558 INFO RPC interface 'supervisor' initialized
2024-12-17 15:00:17,558 INFO supervisord started with pid 8
2024-12-17 15:00:18,583 INFO spawned: 'xvfb' with pid 63
2024-12-17 15:00:18,589 INFO spawned: 'vnc' with pid 64
2024-12-17 15:00:18,616 INFO spawned: 'novnc' with pid 65
2024-12-17 15:00:18,618 INFO spawned: 'selenium-standalone' with pid 67
2024-12-17 15:00:18,626 INFO success: xvfb entered RUNNING state, process has stayed up for > than 0 seconds (startsecs)
2024-12-17 15:00:18,626 INFO success: vnc entered RUNNING state, process has stayed up for > than 0 seconds (startsecs)
2024-12-17 15:00:18,626 INFO success: novnc entered RUNNING state, process has stayed up for > than 0 seconds (startsecs)
2024-12-17 15:00:18,626 INFO success: selenium-standalone entered RUNNING state, process has stayed up for > than 0 seconds (startsecs)
Appending Selenium option: --heartbeat-period 30
Appending Selenium option: --log-level INFO
Appending Selenium option: --http-logs false
Appending Selenium option: --structured-logs false
Appending Selenium option: --reject-unsupported-caps true
Selenium Grid Standalone configuration:
[network]
relax-checks = true
[node]
grid-url = "http://localhost:4444"
session-timeout = "300"
override-max-sessions = false
detect-drivers = false
drain-after-session-count = 0
max-sessions = 1
[[node.driver-configuration]]
display-name = "chrome"
stereotype = '{"browserName": "chrome", "browserVersion": "130.0", "platformName": "Linux", "goog:chromeOptions": {"binary": "/usr/bin/chromium"}, "se:containerName": ""}'
max-sessions = 1
Starting Selenium Grid Standalone...
Tracing is enabled
Classpath will be enriched with these external jars : --ext /external_jars/https/repo1.maven.org/maven2/io/opentelemetry/opentelemetry-exporter-otlp/1.42.1/opentelemetry-exporter-otlp-1.42.1.jar:/external_jars/https/repo1.maven.org/maven2/io/grpc/grpc-netty/1.66.0/grpc-netty-1.66.0.jar:/external_jars/https/repo1.maven.org/maven2/io/netty/netty-codec-http/4.1.113.Final/netty-codec-http-4.1.113.Final.jar:/external_jars/https/repo1.maven.org/maven2/io/opentelemetry/opentelemetry-sdk-trace/1.42.1/opentelemetry-sdk-trace-1.42.1.jar:/external_jars/https/repo1.maven.org/maven2/io/opentelemetry/opentelemetry-sdk-metrics/1.42.1/opentelemetry-sdk-metrics-1.42.1.jar:/external_jars/https/repo1.maven.org/maven2/io/opentelemetry/opentelemetry-sdk-logs/1.42.1/opentelemetry-sdk-logs-1.42.1.jar:/external_jars/https/repo1.maven.org/maven2/io/opentelemetry/opentelemetry-exporter-otlp-common/1.42.1/opentelemetry-exporter-otlp-common-1.42.1.jar:/external_jars/https/repo1.maven.org/maven2/io/opentelemetry/opentelemetry-exporter-sender-okhttp/1.42.1/opentelemetry-exporter-sender-okhttp-1.42.1.jar:/external_jars/https/repo1.maven.org/maven2/io/opentelemetry/opentelemetry-sdk-extension-autoconfigure-spi/1.42.1/opentelemetry-sdk-extension-autoconfigure-spi-1.42.1.jar:/external_jars/https/repo1.maven.org/maven2/io/grpc/grpc-api/1.66.0/grpc-api-1.66.0.jar:/external_jars/https/repo1.maven.org/maven2/io/netty/netty-codec-http2/4.1.100.Final/netty-codec-http2-4.1.100.Final.jar:/external_jars/https/repo1.maven.org/maven2/io/grpc/grpc-core/1.66.0/grpc-core-1.66.0.jar:/external_jars/https/repo1.maven.org/maven2/io/netty/netty-handler-proxy/4.1.100.Final/netty-handler-proxy-4.1.100.Final.jar:/external_jars/https/repo1.maven.org/maven2/com/google/guava/guava/33.2.1-android/guava-33.2.1-android.jar:/external_jars/https/repo1.maven.org/maven2/com/google/errorprone/error_prone_annotations/2.28.0/error_prone_annotations-2.28.0.jar:/external_jars/https/repo1.maven.org/maven2/io/perfmark/perfmark-api/0.27.0/perfmark-api-0.27.0.jar:/external_jars/https/repo1.maven.org/maven2/io/netty/netty-transport-native-unix-common/4.1.113.Final/netty-transport-native-unix-common-4.1.113.Final.jar:/external_jars/https/repo1.maven.org/maven2/io/grpc/grpc-util/1.66.0/grpc-util-1.66.0.jar:/external_jars/https/repo1.maven.org/maven2/io/netty/netty-common/4.1.113.Final/netty-common-4.1.113.Final.jar:/external_jars/https/repo1.maven.org/maven2/io/netty/netty-buffer/4.1.113.Final/netty-buffer-4.1.113.Final.jar:/external_jars/https/repo1.maven.org/maven2/io/netty/netty-transport/4.1.113.Final/netty-transport-4.1.113.Final.jar:/external_jars/https/repo1.maven.org/maven2/io/netty/netty-codec/4.1.113.Final/netty-codec-4.1.113.Final.jar:/external_jars/https/repo1.maven.org/maven2/io/netty/netty-handler/4.1.113.Final/netty-handler-4.1.113.Final.jar:/external_jars/https/repo1.maven.org/maven2/io/opentelemetry/opentelemetry-api/1.42.1/opentelemetry-api-1.42.1.jar:/external_jars/https/repo1.maven.org/maven2/io/opentelemetry/opentelemetry-sdk-common/1.42.1/opentelemetry-sdk-common-1.42.1.jar:/external_jars/https/repo1.maven.org/maven2/io/opentelemetry/opentelemetry-api-incubator/1.42.1-alpha/opentelemetry-api-incubator-1.42.1-alpha.jar:/external_jars/https/repo1.maven.org/maven2/io/opentelemetry/opentelemetry-exporter-common/1.42.1/opentelemetry-exporter-common-1.42.1.jar:/external_jars/https/repo1.maven.org/maven2/com/squareup/okhttp3/okhttp/4.12.0/okhttp-4.12.0.jar:/external_jars/https/repo1.maven.org/maven2/io/opentelemetry/opentelemetry-sdk/1.42.1/opentelemetry-sdk-1.42.1.jar:/external_jars/https/repo1.maven.org/maven2/com/google/code/findbugs/jsr305/3.0.2/jsr305-3.0.2.jar:/external_jars/https/repo1.maven.org/maven2/com/google/code/gson/gson/2.11.0/gson-2.11.0.jar:/external_jars/https/repo1.maven.org/maven2/com/google/android/annotations/4.1.1.4/annotations-4.1.1.4.jar:/external_jars/https/repo1.maven.org/maven2/org/codehaus/mojo/animal-sniffer-annotations/1.24/animal-sniffer-annotations-1.24.jar:/external_jars/https/repo1.maven.org/maven2/io/grpc/grpc-context/1.66.0/grpc-context-1.66.0.jar:/external_jars/https/repo1.maven.org/maven2/io/netty/netty-codec-socks/4.1.100.Final/netty-codec-socks-4.1.100.Final.jar:/external_jars/https/repo1.maven.org/maven2/com/google/guava/failureaccess/1.0.2/failureaccess-1.0.2.jar:/external_jars/https/repo1.maven.org/maven2/com/google/guava/listenablefuture/9999.0-empty-to-avoid-conflict-with-guava/listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar:/external_jars/https/repo1.maven.org/maven2/org/checkerframework/checker-qual/3.42.0/checker-qual-3.42.0.jar:/external_jars/https/repo1.maven.org/maven2/com/google/j2objc/j2objc-annotations/3.0.0/j2objc-annotations-3.0.0.jar:/external_jars/https/repo1.maven.org/maven2/io/netty/netty-resolver/4.1.113.Final/netty-resolver-4.1.113.Final.jar:/external_jars/https/repo1.maven.org/maven2/io/opentelemetry/opentelemetry-context/1.42.1/opentelemetry-context-1.42.1.jar:/external_jars/https/repo1.maven.org/maven2/com/squareup/okio/okio/3.6.0/okio-3.6.0.jar:/external_jars/https/repo1.maven.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.9.10/kotlin-stdlib-jdk8-1.9.10.jar:/external_jars/https/repo1.maven.org/maven2/com/squareup/okio/okio-jvm/3.6.0/okio-jvm-3.6.0.jar:/external_jars/https/repo1.maven.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.9.10/kotlin-stdlib-1.9.10.jar:/external_jars/https/repo1.maven.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.9.10/kotlin-stdlib-jdk7-1.9.10.jar:/external_jars/https/repo1.maven.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-common/1.9.10/kotlin-stdlib-common-1.9.10.jar:/external_jars/https/repo1.maven.org/maven2/org/jetbrains/annotations/13.0/annotations-13.0.jar
List arguments for OpenTelemetry: -Dotel.resource.attributes=service.name=selenium-standalone -Dotel.traces.exporter=otlp -Dotel.java.global-autoconfigure.enabled=true
Dec 17, 2024 3:00:21 PM org.openqa.selenium.grid.config.TomlConfig <init>
WARNING: Please use quotes to denote strings. Upcoming TOML parser will require this and unquoted strings will throw an error in the future
15:00:21.629 INFO [LoggingOptions.configureLogEncoding] - Using the system default encoding
15:00:21.632 INFO [OpenTelemetryTracer.createTracer] - Using OpenTelemetry for tracing
15:00:22.745 INFO [NodeOptions.getSessionFactories] - Detected 5 available processors
15:00:22.812 INFO [NodeOptions.report] - Adding chrome for {"browserName": "chrome","browserVersion": "130.0","goog:chromeOptions": {"binary": "\u002fusr\u002fbin\u002fchromium"},"platformName": "linux","se:containerName": "","se:noVncPort": 7900,"se:vncEnabled": true} 1 times
15:00:22.874 INFO [Node.<init>] - Binding additional locator mechanisms: relative
15:00:22.907 INFO [GridModel.setAvailability] - Switching Node 747d82ef-c32f-4fcc-8dca-a514f9967b27 (uri: http://172.17.0.3:4444) from DOWN to UP
15:00:22.908 INFO [LocalDistributor.add] - Added node 747d82ef-c32f-4fcc-8dca-a514f9967b27 at http://172.17.0.3:4444. Health check every 120s
15:00:23.167 INFO [Standalone.execute] - Started Selenium Standalone 4.25.0 (revision 030fcf7918): http://172.17.0.3:4444
Dec 17, 2024 8:30:23 PM org.openqa.selenium.remote.tracing.opentelemetry.OpenTelemetryTracer createTracer
INFO: Using OpenTelemetry for tracing
Dec 17, 2024 8:30:26 PM org.openqa.selenium.devtools.CdpVersionFinder findNearestMatch
WARNING: Unable to find an exact match for CDP version 130, returning the closest version; found: 129; Please update to a Selenium version that supports CDP version 130
org.openqa.selenium.remote.http.ConnectionFailedException: JdkWebSocket initial request execution error
Build info: version: '4.25.0', revision: '8a8aea2337'
System info: os.name: 'Mac OS X', os.arch: 'x86_64', os.version: '14.6.1', java.version: '17.0.10'
Driver info: driver.version: unknown
at org.openqa.selenium.remote.http.jdk.JdkHttpClient.openSocket(JdkHttpClient.java:248)
at org.openqa.selenium.devtools.Connection.<init>(Connection.java:89)
at org.openqa.selenium.devtools.SeleniumCdpConnection.<init>(SeleniumCdpConnection.java:36)
at org.openqa.selenium.devtools.SeleniumCdpConnection.lambda$create$3(SeleniumCdpConnection.java:103)
at java.base/java.util.Optional.map(Optional.java:260)
at org.openqa.selenium.devtools.SeleniumCdpConnection.create(SeleniumCdpConnection.java:103)
at org.openqa.selenium.devtools.SeleniumCdpConnection.create(SeleniumCdpConnection.java:49)
at org.openqa.selenium.devtools.DevToolsProvider.getImplementation(DevToolsProvider.java:50)
at org.openqa.selenium.devtools.DevToolsProvider.getImplementation(DevToolsProvider.java:29)
at org.openqa.selenium.remote.Augmenter.augment(Augmenter.java:207)
at org.openqa.selenium.remote.Augmenter.augment(Augmenter.java:178)
at SeleniumTestWithWebSockets.testBiDiConnection(SeleniumTestWithWebSockets.java:55)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.testng.internal.invokers.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:141)
at org.testng.internal.invokers.TestInvoker.invokeMethod(TestInvoker.java:686)
at org.testng.internal.invokers.TestInvoker.invokeTestMethod(TestInvoker.java:230)
at org.testng.internal.invokers.MethodRunner.runInSequence(MethodRunner.java:63)
at org.testng.internal.invokers.TestInvoker$MethodInvocationAgent.invoke(TestInvoker.java:992)
at org.testng.internal.invokers.TestInvoker.invokeTestMethods(TestInvoker.java:203)
at org.testng.internal.invokers.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:154)
at org.testng.internal.invokers.TestMethodWorker.run(TestMethodWorker.java:134)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at org.testng.TestRunner.privateRun(TestRunner.java:739)
at org.testng.TestRunner.run(TestRunner.java:614)
at org.testng.SuiteRunner.runTest(SuiteRunner.java:421)
at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:413)
at org.testng.SuiteRunner.privateRun(SuiteRunner.java:373)
at org.testng.SuiteRunner.run(SuiteRunner.java:312)
at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:95)
at org.testng.TestNG.runSuitesSequentially(TestNG.java:1274)
at org.testng.TestNG.runSuitesLocally(TestNG.java:1208)
at org.testng.TestNG.runSuites(TestNG.java:1112)
at org.testng.TestNG.run(TestNG.java:1079)
at com.intellij.rt.testng.IDEARemoteTestNG.run(IDEARemoteTestNG.java:65)
at com.intellij.rt.testng.RemoteTestNGStarter.main(RemoteTestNGStarter.java:105)
Caused by: java.net.ConnectException
at java.net.http/jdk.internal.net.http.common.Utils.toConnectException(Utils.java:1055)
at java.net.http/jdk.internal.net.http.PlainHttpConnection.connectAsync(PlainHttpConnection.java:198)
at java.net.http/jdk.internal.net.http.PlainHttpConnection.checkRetryConnect(PlainHttpConnection.java:230)
at java.net.http/jdk.internal.net.http.PlainHttpConnection.lambda$connectAsync$1(PlainHttpConnection.java:206)
at java.base/java.util.concurrent.CompletableFuture.uniHandle(CompletableFuture.java:934)
at java.base/java.util.concurrent.CompletableFuture$UniHandle.tryFire(CompletableFuture.java:911)
at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:510)
at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1773)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
at java.base/java.lang.Thread.run(Thread.java:840)
Caused by: java.nio.channels.ClosedChannelException
at java.base/sun.nio.ch.SocketChannelImpl.ensureOpen(SocketChannelImpl.java:195)
at java.base/sun.nio.ch.SocketChannelImpl.beginConnect(SocketChannelImpl.java:760)
at java.base/sun.nio.ch.SocketChannelImpl.connect(SocketChannelImpl.java:848)
at java.net.http/jdk.internal.net.http.PlainHttpConnection.lambda$connectAsync$0(PlainHttpConnection.java:183)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:569)
at java.net.http/jdk.internal.net.http.PlainHttpConnection.connectAsync(PlainHttpConnection.java:185)
... 9 moreI tried with different versions so ignore this warning -
WARNING: Unable to find an exact match for CDP version 130, returning the closest version; found: 129; Please update to a Selenium version that supports CDP version 130
This can be reproduce with latest docker image selenium/standalone-chromium:latest or previous versions
Operating System
Mac
Selenium version
4.25 and later
What are the browser(s) and version(s) where you see this issue?
128,129,130,131
What are the browser driver(s) and version(s) where you see this issue?
128,129,130,131
Are you using Selenium Grid?
No