SeleniumHQ / selenium

A browser automation framework and ecosystem.
https://selenium.dev
Apache License 2.0
30.43k stars 8.15k forks source link

[🐛 Bug]: networkConnectionEnabled capability chromeOptions does not work anymore with Selenium 4.9.0. #11923

Closed czp13 closed 1 year ago

czp13 commented 1 year ago

What happened?

The newest version of Selinium is not supporting anymore to setup networkConnectionEnabled true:

ChromeOptions chromeOptions = new ChromeOptions();       
chromeOptions.setCapability("networkConnectionEnabled", true);

Causing this:

Caused by: java.lang.IllegalArgumentException: Illegal key values seen in w3c capabilities: [networkConnectionEnabled]

This was used for mobile testing.

How can we reproduce the issue?

With updating the following dependency:

 <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-remote-driver</artifactId>
            <version>4.8.3</version>
</dependency>

To:

 <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-remote-driver</artifactId>
            <version>4.9.0</version>
</dependency>

And using the remoteWebDriver like this:

    ChromeOptions chromeOptions =                new ChromeOptions();
   URL remoteURL = // generate some remote URL
   driver = new RemoteWebDriver(remoteURL, chromeOptions);

Will generate the exception.


### Relevant log output

```shell
Command: [null, newSession {capabilities=[Capabilities {browserName: chrome, goog:chromeOptions: {args: [--remote-allow-origins=*, --headless, --disable-gpu], extensions: [], mobileEmulation: {deviceName: Laptop with touch}}, networkConnectionEnabled: true}]}]
    at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:561)
    at org.openqa.selenium.remote.RemoteWebDriver.startSession(RemoteWebDriver.java:229)
    at org.openqa.selenium.remote.RemoteWebDriver.<init>(RemoteWebDriver.java:157)
    at org.openqa.selenium.chromium.ChromiumDriver.<init>(ChromiumDriver.java:101)
    at org.openqa.selenium.chrome.ChromeDriver.<init>(ChromeDriver.java:88)
    at org.openqa.selenium.chrome.ChromeDriver.<init>(ChromeDriver.java:84)
    at org.openqa.selenium.chrome.ChromeDriver.<init>(ChromeDriver.java:73)
    at com.vaadin.flow.testutil.ChromeDeviceTest.setup(ChromeDeviceTest.java:83)
    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.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
    at org.junit.internal.runners.statements.RunBefores.invokeMethod(RunBefores.java:33)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
    at com.vaadin.testbench.parallel.ParallelRunner$1.evaluate(ParallelRunner.java:465)
    at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:61)
    at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:61)
    at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
    at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
    at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
    at org.apache.maven.surefire.junitcore.pc.Scheduler$1.run(Scheduler.java:345)
    at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
    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:833)
Caused by: java.lang.IllegalArgumentException: Illegal key values seen in w3c capabilities: [networkConnectionEnabled]
    at org.openqa.selenium.remote.NewSessionPayload.lambda$validate$4(NewSessionPayload.java:175)
    at java.base/java.util.stream.ReferencePipeline$15$1.accept(ReferencePipeline.java:540)
    at java.base/java.util.stream.ReferencePipeline$15$1.accept(ReferencePipeline.java:541)
    at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
    at java.base/java.util.stream.ReferencePipeline$15$1.accept(ReferencePipeline.java:541)
    at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1625)
    at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
    at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
    at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
    at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
    at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596)
    at org.openqa.selenium.remote.NewSessionPayload.validate(NewSessionPayload.java:179)
    at org.openqa.selenium.remote.NewSessionPayload.<init>(NewSessionPayload.java:91)
    at org.openqa.selenium.remote.NewSessionPayload.create(NewSessionPayload.java:124)
    at org.openqa.selenium.remote.NewSessionPayload.create(NewSessionPayload.java:112)
    at org.openqa.selenium.remote.ProtocolHandshake.createSession(ProtocolHandshake.java:67)
    at org.openqa.selenium.remote.HttpCommandExecutor.execute(HttpCommandExecutor.java:165)
    at org.openqa.selenium.remote.service.DriverCommandExecutor.invokeExecute(DriverCommandExecutor.java:183)
    at org.openqa.selenium.remote.service.DriverCommandExecutor.execute(DriverCommandExecutor.java:158)
    at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:543)
    ... 31 more


### Operating System

macOS Monterey

### Selenium version

Selenium Java 4.9.0

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

Chrome 112.0.5615.49 

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

ChromeDriver 4.9.0

### Are you using Selenium Grid?

_No response_
github-actions[bot] commented 1 year ago

@czp13, thank you for creating this issue. We will troubleshoot it as soon as we can.


Info for maintainers

Triage this issue by using labels.

If information is missing, add a helpful comment and then I-issue-template label.

If the issue is a question, add the I-question label.

If the issue is valid but there is no time to troubleshoot it, consider adding the help wanted label.

If the issue requires changes or fixes from an external project (e.g., ChromeDriver, GeckoDriver, MSEdgeDriver, W3C), add the applicable G-* label, and it will provide the correct link and auto-close the issue.

After troubleshooting the issue, please add the R-awaiting answer label.

Thank you!

czp13 commented 1 year ago

Potential cause changes here made inNewSessionPayload:

TheinNewSessionPayload was refactored, and changed much from the version before:

Any workaround for this? Thank you! 🙏

diemol commented 1 year ago

The workaround is to use W3C only capabilities. Where are you using that capability?

titusfortner commented 1 year ago

Yes, this needs to be set in goog:chromeOptions. There has been a warning displayed for quite a while that it can't be placed in the top level list of capabilities.

It should work to do:

options.setExperimentalOption("networkConnectionEnabled", true)

But also, I'm not sure you need it for anything? What is your use case?

czp13 commented 1 year ago

Thank you @titusfortner and @diemol. I am trying now with the options.setExperimentalOption("networkConnectionEnabled", true). Let's see.

It is an old code piece in our testing setup. The information I have is that this was needed for offline emulation, and needed to add some device mod as well.

Here:

Code piece:

    @Before
    @Override
    public void setup() throws Exception {
        ChromeOptions chromeOptions = customizeChromeOptions(
                new ChromeOptions());

        WebDriver driver;
        if (Browser.CHROME == getRunLocallyBrowser()) {
            driver = new ChromeDriver(chromeOptions);
        } else {
            URL remoteURL = new URL(getHubURL());
            driver = new RemoteWebDriver(remoteURL, chromeOptions);
            setDevToolsRuntimeCapabilities((RemoteWebDriver) driver, remoteURL);
        }

        devTools = new DevToolsWrapper(driver);

        setDriver(TestBench.createDriver(driver));
    }

protected ChromeOptions customizeChromeOptions(
            ChromeOptions chromeOptions) {
        // Unfortunately using offline emulation ("setNetworkConnection"
        // session command) in Chrome requires the "networkConnectionEnabled"
        // capability, which is:
        // - Not W3C WebDriver API compliant, so we disable W3C protocol
        // - device mode: mobileEmulation option with some device settings

        final Map<String, Object> mobileEmulationParams = new HashMap<>();
        mobileEmulationParams.put("deviceName", "Laptop with touch");

        // chromeOptions.setExperimentalOption("w3c", false);
        chromeOptions.setExperimentalOption("mobileEmulation",
                mobileEmulationParams);
        chromeOptions.setCapability("networkConnectionEnabled", true);("networkConnectionEnabled", true);

        if (getDeploymentHostname().equals("localhost")) {
            // Use headless Chrome for running locally
            if (!isJavaInDebugMode()) {
                chromeOptions.addArguments("--headless", "--disable-gpu");
            }
        } else {
            // Enable service workers over http remote connection
            chromeOptions.addArguments(String.format(
                    "--unsafely-treat-insecure-origin-as-secure=%s",
                    getRootURL()));

            // NOTE: this flag is not supported in headless Chrome, see
            // https://crbug.com/814146

            // For test stability on Linux when not running headless.
            // https://stackoverflow.com/questions/50642308/webdriverexception-unknown-error-devtoolsactiveport-file-doesnt-exist-while-t
            chromeOptions.addArguments("--disable-dev-shm-usage");
        }

        return chr
}
titusfortner commented 1 year ago

Hmm, it doesn't show up as required in their docs - https://chromedriver.chromium.org/mobile-emulation Maybe it used to be and isn't now? /shrug

czp13 commented 1 year ago

Well, I tried with your idea and it seems like this param was needed, I got this error now:

Starting ChromeDriver 112.0.5615.49 (bd2a7bcb881c11e8cfe3078709382934e3916914-refs/branch-heads/5615@{#936}) on port 14235
Only local connections are allowed.
Please see https://chromedriver.chromium.org/security-considerations for suggestions on keeping ChromeDriver safe.
ChromeDriver was started successfully.

Full error log:

Could not start a new session. Response code 400. Message: invalid argument: entry 0 of 'firstMatch' is invalid
from invalid argument: cannot parse capability: goog:chromeOptions
from invalid argument: unrecognized chrome option: networkConnectionEnabled 
Host info: host: 'fv-az402-462', ip: '10.1.0.9'
Build info: version: '4.9.0', revision: 'd7057100a6'
System info: os.name: 'Linux', os.arch: 'amd64', os.version: '5.15.0-1035-azure', java.version: '17.0.6'
Driver info: org.openqa.selenium.chrome.ChromeDriver
Command: [null, newSession {capabilities=[Capabilities {browserName: chrome, goog:chromeOptions: {args: [--remote-allow-origins=*, --headless, --disable-gpu], extensions: [], mobileEmulation: {deviceName: Laptop with touch}, networkConnectionEnabled: true}}]}]
org.openqa.selenium.SessionNotCreatedException: 
Could not start a new session. Response code 400. Message: invalid argument: entry 0 of 'firstMatch' is invalid
from invalid argument: cannot parse capability: goog:chromeOptions
from invalid argument: unrecognized chrome option: networkConnectionEnabled 
Host info: host: 'fv-az402-462', ip: '10.1.0.9'
Build info: version: '4.9.0', revision: 'd7057100a6'
System info: os.name: 'Linux', os.arch: 'amd64', os.version: '5.15.0-1035-azure', java.version: '17.0.6'
Driver info: org.openqa.selenium.chrome.ChromeDriver
Command: [null, newSession {capabilities=[Capabilities {browserName: chrome, goog:chromeOptions: {args: [--remote-allow-origins=*, --headless, --disable-gpu], extensions: [], mobileEmulation: {deviceName: Laptop with touch}, networkConnectionEnabled: true}}]}]
    at org.openqa.selenium.remote.ProtocolHandshake.createSession(ProtocolHandshake.java:136)
    at org.openqa.selenium.remote.ProtocolHandshake.createSession(ProtocolHandshake.java:94)
    at org.openqa.selenium.remote.ProtocolHandshake.createSession(ProtocolHandshake.java:68)
    at org.openqa.selenium.remote.HttpCommandExecutor.execute(HttpCommandExecutor.java:165)
    at org.openqa.selenium.remote.service.DriverCommandExecutor.invokeExecute(DriverCommandExecutor.java:183)
    at org.openqa.selenium.remote.service.DriverCommandExecutor.execute(DriverCommandExecutor.java:158)
    at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:543)
    at org.openqa.selenium.remote.RemoteWebDriver.startSession(RemoteWebDriver.java:229)
    at org.openqa.selenium.remote.RemoteWebDriver.<init>(RemoteWebDriver.java:157)
    at org.openqa.selenium.chromium.ChromiumDriver.<init>(ChromiumDriver.java:101)
    at org.openqa.selenium.chrome.ChromeDriver.<init>(ChromeDriver.java:88)
    at org.openqa.selenium.chrome.ChromeDriver.<init>(ChromeDriver.java:84)
    at org.openqa.selenium.chrome.ChromeDriver.<init>(ChromeDriver.java:73)
    at com.vaadin.flow.testutil.ChromeDeviceTest.setup(ChromeDeviceTest.java:83)
    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.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
    at org.junit.internal.runners.statements.RunBefores.invokeMethod(RunBefores.java:33)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
    at com.vaadin.testbench.parallel.ParallelRunner$1.evaluate(ParallelRunner.java:465)
    at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:61)
    at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:61)
    at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
    at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
    at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
    at org.apache.maven.surefire.junitcore.pc.Scheduler$1.run(Scheduler.java:345)
    at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
    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:833)
Starting ChromeDriver 112.0.5615.49 (bd2a7bcb881c11e8cfe3078709382934e3916914-refs/branch-heads/5615@{#936}) on port 14235
Only local connections are allowed.
Please see https://chromedriver.chromium.org/security-considerations for suggestions on keeping ChromeDriver safe.
ChromeDriver was started successfully.
czp13 commented 1 year ago

@titusfortner: Is not it possible that this change is a regression, backward compatibility broking change? I cannot find the proper parameter list, and configuration and the old one is not supported anymore

diemol commented 1 year ago

If your code is W3C compliant, it is a regression. Therefore we need a piece of code that we can simply copy and paste in our IDE to reproduce the issue. When that is present, I'd be happy to reopen and triage.

czp13 commented 1 year ago

It is not W3C compliant I believe, but we needed to use it. The best would be to somehow replace it with the W3C-compliant version of it, I can share again the code piece. But basically, this is it, from here:

@diemlo: Any idea how to rewrite this to be w3c compliant? 🙇

titusfortner commented 1 year ago

from invalid argument: unrecognized chrome option: networkConnectionEnabled

The error message is saying that chromedriver doesn't recognize this parameter, which should mean that it isn't necessary for your use case. Did you try just not setting it? Most likely it was being ignored in the previous version of Selenium.

If you don't set it and get an error, let us know what the error is.

czp13 commented 1 year ago

@titusfortner: Thank you for your ideas. I did not try to not set it, I could try it.

What I did was refactor and remove many code pieces in our testing repository/project. The code removals solved my problem :), and it worked and the test passed without problems with the newest Selenium.

I hope I can get approved soon for my PR and then this will be solved. Also understood through my investigations that this whole networkConnectionEnabled was used to be able to use Aeroplane mode and other modes. (NetworkConnection.ConnectionType.AIRPLANE_MODE).

czp13 commented 1 year ago

@titusfortner: I removed the discussed line, this one: chromeOptions.setCapability("networkConnectionEnabled", true);

Got a different exception:

org/openqa/selenium/devtools/v109/network/Network
java.lang.NoClassDefFoundError: org/openqa/selenium/devtools/v109/network/Network
    at com.vaadin.flow.testutil.DevToolsWrapper.setOfflineEnabled(DevToolsWrapper.java:53)
    at com.vaadin.flow.navigate.ServiceWorkerIT.offlineTsView_navigateToServerView_offlineStubShown(ServiceWorkerIT.java:232)
    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.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
    at com.vaadin.testbench.parallel.ParallelRunner$TBMethod.invokeExplosively(ParallelRunner.java:491)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at com.vaadin.testbench.parallel.ParallelRunner$1.evaluate(ParallelRunner.java:465)
    at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:61)
    at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:61)
    at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
    at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
    at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
    at org.apache.maven.surefire.junitcore.pc.Scheduler$1.run(Scheduler.java:345)
    at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
    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:833)
Caused by: java.lang.ClassNotFoundException: org.openqa.selenium.devtools.v109.network.Network
    ... 27 more
Starting ChromeDriver 112.0.5615.49 (bd2a7bcb881c11e8cfe3078709382934e3916914-refs/branch-heads/5615@{#936}) on port 10552
Only local connections are allowed.
Please see https://chromedriver.chromium.org/security-considerations for suggestions on keeping ChromeDriver safe.
ChromeDriver was started successfully.
czp13 commented 1 year ago

Looks like this class is not existing anymore: import org.openqa.selenium.devtools.v109.network.Network;

I will investigate later on, I can choose from many versions, if you have any idea which one is good it appreciated if not, then I will investigate later:

image
titusfortner commented 1 year ago

4.9 only supports CDP for v110, v111, and v112. Please update your chrome version and any references to the old version in your code. Updating versions is a pain and we're actively working to implement these things with a cross-browser WebDriver-BiDi protocol. The Network module was just adde to the spec, so hopefully we'll have future compatible code available soon.

networkConnectionEnabled was used to be able to use Aeroplane mode and other modes

Oh interesting, thanks for sharing that; I'm not very familiar with the mobile package.

czp13 commented 1 year ago

Thank you @titusfortner. I tried with v110, and some tests are still failing, but I hope, and believe we are closer to fixing this problem. Indeed this is more complicated, usually updating a dependency is just bumping the version in pom.xml, but here much more is needed, and maybe this jump from 4.8 to 4.9 is bigger than usual :).

Thanks for the discussion, ideas/insights, guide tho! 🙇

github-actions[bot] commented 10 months ago

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.