Repository navigation
feat: add the Selenium bridge for RemoteWebDriver and BiDi - #2463
Merged
Merged
Conversation
Converts the build to a multi-project one. The core stays at the root, and the new selenium-bridge subproject publishes io.appium:java-client-selenium-bridge with the version of the core. It depends on the core and on selenium-remote-driver within the same range as selenium-api, so both resolve to one Selenium version. The repositories and the common POM data are shared by both projects, and JReleaser stages the artifacts of both. CI needs no change, because the e2eAndroidTest and e2eIosTest tasks exist in both projects and run together. The publication was verified with a JReleaser dry run: one Maven Central bundle that contains both modules. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
AppiumDriver is not a RemoteWebDriver anymore and does not implement HasBiDi. SeleniumBridge.asRemoteWebDriver adapts it for the Selenium code that needs them, for example the Augmenter and the BiDi modules. The result is a RemoteWebDriver attached to the session of the Appium driver. Its commands go through the command executor of the Appium driver, so both drivers share the session and the HTTP client, and quit() quits the session. BiDi is created on the first use from the webSocketUrl capability, with the timeouts, proxy, credentials and SSL context of the AppiumClientConfig. The overload with an HttpClient.Factory customizes the WebSocket client. maybeGetBiDi() is overridden without @OverRide, because Selenium's modules still call it and Selenium is going to delete it. getHandle() is the real override. AppiumCommandExecutor#getClientConfig is added to the core for this. Tests run against a fake Appium HTTP server and a fake BiDi WebSocket server. The BiDi e2e tests that were removed from the core are restored here. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Adds the Selenium interoperability page and links it from the README and the v10 to v11 migration guide. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
mykola-mokhnach
requested review from
SrinivasanTarget,
saikrishna321 and
valfirst
as code owners
October 5, 2026 08:52
The bridge overrode maybeGetBiDi(), which Selenium deprecated for removal, and attached to the session through protected RemoteWebDriver hooks. Build BridgedRemoteWebDriver with the public RemoteWebDriver constructor instead. The command executor answers the new session command with the existing Appium session and capabilities, so Selenium takes the session over and creates the BiDi connection itself from the webSocketUrl capability. No deprecated Selenium API is overridden or called anymore (maybeGetBiDi, Response#setStatus, getBiDi in the tests), so no warning needs suppressing, and the module compiles with -Xlint:deprecation,removal. The e2e BiDi tests use the LogInspector module for the same reason. BiDi now connects when the bridge is created. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2 tasks done
A new script resolves the versions to install from the npm dist-tags. If the server and the platform driver both have a beta release that is newer than their latest stable one, both are installed in the beta version, so incompatibilities with the upcoming releases show up early. Otherwise the stable versions are used. The Flutter tests always use the stable versions. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
simulator-action v6 can wait until the background CPU usage of the simulator subsides. Waiting for up to 180 seconds avoids starting the tests while the simulator is still busy. If it does not settle in time, the action only warns. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
valfirst
approved these changes
Oct 5, 2026
harsha509
reviewed
Oct 5, 2026
harsha509
reviewed
Oct 5, 2026
harsha509
reviewed
Oct 5, 2026
harsha509
reviewed
Oct 5, 2026
harsha509
reviewed
Oct 5, 2026
- Add a no-arg constructor to BridgedRemoteWebDriver, which the Selenium Augmenter calls on its generated subclass. Without it, any matching augmentation (for example the se:cdp capability) failed. - Ignore the quit command until the bridge is created. Selenium quits the driver if its constructor fails, which ended the session of the Appium driver. - Return the same bridge for the same Appium driver, so repeated calls do not open more BiDi connections, and add closeBiDi() to release the connection without quitting the session. quit() also releases the HTTP clients of the connection. The e2e tests and the docs close the connection now. - Document that elements are not interchangeable between the two drivers. - Drop AppiumCommandExecutor#getClientConfig in favor of the existing Lombok getter getAppiumClientConfig. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
1 of 4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Stage 5 of cutting java-client's dependency on Selenium down to
selenium-api. #2462 removedselenium-remote-driverand BiDi from the core, soAppiumDriveris no longer aRemoteWebDriverand does not implementHasBiDi. This PR adds an optional artifact,io.appium:java-client-selenium-bridge, for the code that still needs them, such as the SeleniumAugmenteror the BiDi modules (LogInspector, etc.). The core is unchanged apart from one getter.What changed
selenium-bridgesubproject publishesjava-client-selenium-bridgewith the version of the core. It depends on the core and onselenium-remote-driverwithin the same[4.50.0, 5.0)range asselenium-api, so both resolve to one Selenium version. Repositories and the common POM data are shared.SeleniumBridge.asRemoteWebDriver(driver)returns a SeleniumRemoteWebDriverthat works in the session of the Appium driver. Commands go through the command executor of the Appium driver, so both drivers share the session and the HTTP client.quit()quits the session. An overload takes a SeleniumHttpClient.Factoryfor the BiDi WebSocket.RemoteWebDriver(CommandExecutor, Capabilities, HttpClient.Factory, ClientConfig)constructor. The executor answers the new session command with the existing Appium session, so Selenium takes it over and creates the BiDi connection itself from thewebSocketUrlcapability, with the timeouts, proxy, credentials and SSL context of theAppiumClientConfig. Nothing deprecated is overridden or called (maybeGetBiDi,Response#setStatus), and the module compiles with-Xlint:deprecation,removal.AppiumCommandExecutor#getClientConfig().docs/selenium-bridge.md, linked from the README and the migration guide.How it was verified
quit(),Augmenter, the BiDi connection,LogInspectorevents and the missing-capability case.AndroidBiDiTestandIOSBiDiTest, removed in feat!: replace selenium-remote-driver, selenium-http and selenium-json #2462, are restored as e2e tests of the bridge, written with the SeleniumLogInspectormodule. They run with the existinge2eAndroidTestande2eIosTesttasks, so CI needs no change../gradlew publishstages both modules, and a JReleaser dry run (jreleaserDeploy) with a throwaway key verified the POMs of both, signed both, and built a single Maven Central bundle containing the core and the bridge../gradlew build: the same 3 environment-only failures as on master (TimeoutTest,StorageTest,DesktopBrowserCompatibilityTest). Checkstyle and Javadoc are clean for both projects.Known issues / follow-ups
RemoteWebDriverand the BiDi classes of Selenium, so the Selenium snapshot job may fail first when Selenium changes them. That is the reason it is a separate artifact.webSocketUrlcapability.