Skip to content

feat!: replace selenium-remote-driver, selenium-http and selenium-json - #2462

Open
mykola-mokhnach wants to merge 3 commits into
masterfrom
stage5
Open

mykola-mokhnach wants to merge 3 commits into
masterfrom
stage5

Conversation

@mykola-mokhnach

@mykola-mokhnach mykola-mokhnach commented Oct 3, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Stage 4b of cutting java-client's dependency on Selenium down to selenium-api. This replaces selenium-remote-driver, selenium-http and selenium-json (and selenium-os, whose last use went away with #2460) with code maintained in this repo. Guava, OpenTelemetry and selenium-manager no longer come in transitively either.

Runtime classpath after this PR: selenium-api, gson, byte-buddy (now declared explicitly), slf4j-api, jspecify.

The minimum supported Selenium version is now 4.50.0. The vendored code is adapted from that release.

What changed

  • io.appium.java_client.http: transport SPI (HttpClient, HttpClient.Factory, requests/responses, filters, WebSocket) with a default java.net.http implementation. Self-contained, guarded by checkstyle import control.
  • internal.json.WireJson: Gson-based wire JSON. Integers and whole numbers are read as Long, others as Double, and values are written like Selenium's Json does for the types Appium sends.
  • remote: Command, Response, SessionId, DriverCommand, ErrorCodes/ErrorHandler, W3C codecs, a W3C-only handshake, a standalone AppiumCommandExecutor, and the AppiumRemoteWebDriver / AppiumWebElement base classes.
  • AppiumClientConfig is standalone and implements http.ClientConfig.
  • Dropped, because Appium's base driver does not route them: the Selenium Grid endpoints GET/POST/DELETE /session/:id/se/files (downloads), POST /session/:id/se/file (file upload) and POST /session/:id/se/event (session events). Also dropped are the Selenium-side web storage commands (JavaScript sent to /execute/sync, deprecated in Selenium), DevTools over the se:cdp WebSocket and OpenTelemetry tracing; none of these are Appium endpoints. POST /session/:id/goog/cdp/execute (ExecuteCDPCommand) is kept.
  • Kept, because Appium's base driver routes them (and proxies them to chromedriver in web contexts): shadow DOM, virtual authenticators, FedCM and /se/log.
  • BiDi is removed from AppiumDriver. Selenium deprecated HasBiDi#getBiDi for removal and reworked the API (getHandle() doesn't exist in older releases), so it moves to a separate bridge module in a follow-up. The URL stays available in the webSocketUrl capability.
  • Guava is replaced with JDK code and small internal helpers.

Small fixes found on the way:

  • AppiumClientConfig#withFilter dropped the Appium user-agent and idempotency filters.
  • wsTimeout was reset to the default when other settings changed.
  • driver.close() threw an NPE when the server returned no value.

How it was verified

Commits are ordered so the behavior is pinned before it is replaced:

  1. Golden tests recorded against the Selenium implementation: request encoding for every DriverCommand and MobileCommand, JSON serialization, response decoding (incl. number types), W3C error mapping, ~100 driver API calls, session creation failures and direct connect.
  2. New layers are added next to the old ones, each with its own tests (local HTTP and WebSocket servers for the transport).
  3. The swap commit replays the goldens against the new stack. Requests, return values and exceptions are unchanged. The only differences are intentional: dropped commands that Appium does not serve, exception classes now owned by java-client, and a clearer error for an empty error body.
  4. Shadow DOM, virtual authenticator and FedCM commands are encoded exactly like Selenium 4.50.0 (compared against its recorded goldens), and have driver-level scenarios.
  5. AppiumDriverOverHttpTest runs the full stack against a real local HTTP server (headers, HTTP/1.1, JSON, error mapping, connection failure).

Unit tests: 188 run, the same 3 environment-only failures as on master (TimeoutTest, StorageTest, DesktopBrowserCompatibilityTest). Checkstyle, Javadoc and compilation of all e2e source sets are clean.

Breaking changes

See docs/v10-to-v11-migration-guide.md. In short:

BREAKING CHANGE: Minimum selenium-api is 4.50.0. selenium-support, -remote-driver and the other modules are no longer dependencies, so declare them yourself if you use them.
BREAKING CHANGE: AppiumDriver is no longer a RemoteWebDriver and returns AppiumWebElement instead of RemoteWebElement. Code typed against WebDriver/WebElement is unaffected.
BREAKING CHANGE: Response, Command, CommandPayload, SessionId, DriverCommand, ExecuteMethod and the error types moved to io.appium.java_client.remote. CommandInfo is replaced by AppiumCommandInfo.
BREAKING CHANGE: org.openqa.selenium.remote.http is replaced by io.appium.java_client.http, including the HttpClient.Factory parameter of the driver constructors. Constructors taking a Selenium ClientConfig are removed.
BREAKING CHANGE: AppiumClientConfig, AppiumCommandExecutor, AppiumW3CHttpCommandCodec and ErrorCodesMobile no longer extend Selenium classes.
BREAKING CHANGE: HasBiDi, getBiDi() and maybeGetBiDi() are removed from AppiumDriver. The two BiDi e2e tests are removed until the bridge module exists.

Known issues / follow-ups

  • README compatibility matrix is not updated (done at release).
  • Next: the BiDi bridge module.

🤖 Generated with Claude Code

@mykola-mokhnach
mykola-mokhnach marked this pull request as draft October 3, 2026 19:41
@mykola-mokhnach mykola-mokhnach changed the title Stage5 feat!: replace selenium-remote-driver, selenium-http and selenium-json Oct 3, 2026
@eglitise

eglitise commented Oct 3, 2026

Copy link
Copy Markdown

Browser-only features are dropped: virtual authenticators, FedCM, downloads, shadow DOM, web storage, file upload, DevTools, tracing.

I haven't looked into the code, but Appium's base-driver does support endpoints relating to several of these features.

manage().logs() still uses Selenium's /se/log routes, which Appium servers don't serve.

They are actually served: https://appium.io/docs/en/latest/reference/api/others/#selenium-protocol

AppiumDriver now extends AppiumRemoteWebDriver, which sends commands through
AppiumCommandExecutor, the W3C codecs, the handshake and the HTTP client that
are maintained in this project. They are adapted from the Selenium 4.50.0
remote driver, which becomes the minimum supported selenium-api version. The
Selenium remote layer, its HTTP client and JSON library are no longer
dependencies, and neither are Guava, OpenTelemetry and selenium-manager that
came with them. The runtime classpath is selenium-api, gson, byte-buddy,
slf4j-api and jspecify.

The new code consists of:
- an HTTP/WebSocket transport (io.appium.java_client.http) with a default
  java.net.http implementation;
- a Gson-based JSON layer that keeps the selenium-json number semantics;
- the command and response types, W3C codecs, handshake and error mapping;
- AppiumRemoteWebDriver and AppiumWebElement.

Golden files recorded on Selenium 4.50.0 pin the requests the drivers send,
the values they return and the exceptions they throw. Replayed against the new
stack they are unchanged, apart from the dropped commands, the exception
classes owned by java-client and a clearer error for an empty error body. A
test against a local HTTP server covers the default HTTP client, the headers
and the error mapping end to end. Set GOLDEN_UPDATE=1 to regenerate them.

Browser-only features are dropped: virtual authenticators, FedCM, downloads,
shadow DOM, web storage, file upload, DevTools and tracing. BiDi support is
removed from the driver and moves to a separate module.

BREAKING CHANGE: java-client requires selenium-api 4.50.0 or newer.
AppiumDriver is not a RemoteWebDriver anymore and returns AppiumWebElement
instead of RemoteWebElement. Response, Command, SessionId, CommandPayload,
DriverCommand, ExecuteMethod and the error types moved to
io.appium.java_client.remote, and org.openqa.selenium.remote.http is replaced
by io.appium.java_client.http, including the HttpClient.Factory parameter of
the driver constructors. AppiumClientConfig, AppiumCommandExecutor,
AppiumW3CHttpCommandCodec and ErrorCodesMobile no longer extend Selenium
classes, the constructors taking a Selenium ClientConfig are removed, and
HasBiDi, getBiDi and maybeGetBiDi are removed from AppiumDriver. See
docs/v10-to-v11-migration-guide.md.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Appium's base driver routes these W3C and extension endpoints (and proxies
them to chromedriver in web contexts), so dropping them removed working
features. AppiumRemoteWebDriver implements HasVirtualAuthenticator and
HasFederatedCredentialManagement again, AppiumWebElement#getShadowRoot is
back, and the commands are defined in DriverCommand and the W3C codec,
ported from Selenium 4.50.0. Their encoding is identical to the Selenium
recording, and driver scenarios cover the three features.

The /se/log routes used by manage().logs() are served by Appium too, so the
migration guide no longer lists them as unsupported. Still dropped because
Appium does not route them: downloads, file upload, web storage, DevTools and
tracing.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@mykola-mokhnach

Copy link
Copy Markdown
Contributor Author

I haven't looked into the code, but Appium's base-driver does support endpoints relating to several of these features.

You're right, thanks. I checked the base-driver routes: shadow DOM (/element/:id/shadow, /shadow/:id/element(s)), WebAuthn (/webauthn/...) and FedCM (/fedcm/...) are routed, and Appium proxies them to chromedriver in web contexts. The interfaces for them (HasVirtualAuthenticator, HasFederatedCredentialManagement) are in selenium-api, so there was no reason to drop them. 325f483 restores all three, with the command encoding identical to Selenium 4.50.0 and driver-level test scenarios.

They are actually served: https://appium.io/docs/en/latest/reference/api/others/#selenium-protocol

Also right. The /se/log and /se/log/types routes were already in the codec, and manage().logs() keeps using them. My "not served" note was wrong, so I've removed it from the migration guide.

Still dropped, because base-driver doesn't route them: downloads (/se/files), file upload (/se/file), web storage, DevTools and tracing. Let me know if you know of Appium drivers that do handle any of these.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@eglitise

eglitise commented Oct 4, 2026

Copy link
Copy Markdown

downloads (/se/files), file upload (/se/file), web storage, DevTools and tracing

It's not clear to me which exact endpoints for web storage, DevTools and tracing are being dropped here, if they even are endpoints.
If DevTools refers to the Chromium CDP endpoints, one such endpoint is also supported by Appium: https://appium.io/docs/en/latest/reference/api/others/#executecdp

@mykola-mokhnach

Copy link
Copy Markdown
Contributor Author

It's not clear to me which exact endpoints for web storage, DevTools and tracing are being dropped here, if they even are endpoints.

You're right, only some of these are endpoints. The dropped ones that are:

  • GET/POST/DELETE /session/:id/se/files (downloads)
  • POST /session/:id/se/file (file upload)
  • POST /session/:id/se/event (session events, which I hadn't listed before)

These are Selenium Grid routes that base-driver doesn't serve.

The rest are not endpoints:

  • Web storage was a set of Selenium commands that send JavaScript to POST /session/:id/execute/sync (and are deprecated in Selenium 4.50).
  • DevTools opens a CDP WebSocket from the se:cdp capability, which Appium never sets.
  • Tracing was OpenTelemetry spans around commands.

If DevTools refers to the Chromium CDP endpoints, one such endpoint is also supported by Appium

It isn't affected. POST /session/:id/goog/cdp/execute is untouched and still available through ExecuteCDPCommand#executeCdpCommand. I've updated the PR description with the exact list.

@mykola-mokhnach
mykola-mokhnach marked this pull request as ready for review October 4, 2026 19:01

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants