[java] Check the resolved driver for JS support in By.getJavascriptExecutor() - #17907
[java] Check the resolved driver for JS support in By.getJavascriptExecutor()#17907Mochxd wants to merge 1 commit into
Conversation
PR Summary by QodoFix By.getJavascriptExecutor() to validate unwrapped driver JS support
AI Description
Diagram
High-Level Assessment
Files changed (2)
|
Code Review by Qodo
1. No cross-binding comparison noted
|
9ce385e to
bdc7fc4
Compare
| WebDriver driver = getWebDriver(context); | ||
|
|
||
| if (!(context instanceof JavascriptExecutor)) { | ||
| if (!(driver instanceof JavascriptExecutor)) { |
There was a problem hiding this comment.
1. No cross-binding comparison noted 📘 Rule violation ≡ Correctness
This change alters user-visible Java behavior for relative locators by accepting wrapped contexts whose unwrapped driver supports JavaScript, but the PR does not document any comparison with other language bindings. Without an explicit cross-binding check, similar APIs may diverge in observable behavior across Selenium bindings.
Agent Prompt
## Issue description
A user-visible behavior change was made in the Java binding (`By.getJavascriptExecutor()`), but there is no evidence in-code (comments/docs) that the behavior was compared with at least one other Selenium language binding as required.
## Issue Context
PR Compliance requires verifying cross-language consistency (or documenting intentional divergence) when changing user-visible behavior in a binding.
## Fix Focus Areas
- java/src/org/openqa/selenium/By.java[153-156]
- java/test/org/openqa/selenium/ByTest.java[188-199]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
|
Code review by qodo was updated up to the latest commit bdc7fc4 |
🔗 Related Issues
No existing issue. I hit this while looking at how relative locators resolve their search context.
💥 What does this PR do?
By.getJavascriptExecutor()resolves the driver withgetWebDriver(context), which unwraps aWrapsDriver, but then checkscontext instanceof JavascriptExecutorand castsdriver. The guard and the cast look at two different objects.The practical effect is that element-scoped relative locators throw.
RemoteWebElementimplementsWrapsDriverbut notJavascriptExecutor, so:fails with
IllegalArgumentException: Context does not provide a mechanism to execute JS: ...even though the driver it just unwrapped can execute JavaScript perfectly well. The same call works when made on the driver.The mismatch can also turn an intended
IllegalArgumentExceptioninto aClassCastExceptionif a context is itself aJavascriptExecutorwhile the driver it wraps is not.Checking
driverinstead ofcontextfixes both, and the rejection path is unchanged when the resolved driver genuinely can't run JavaScript.🔧 Implementation Notes
One-word change, since
getWebDriver()already does the unwrapping. Left the exception message pointing atcontext, as that's the object the caller passed in.Both call sites already treat this as driver-based:
RelativeLocatoruses the returned executor directly, andRelativeLocatorServerSidecallsgetWebDriver(context)on the next line.A unit test covers a context that wraps a JavaScript-capable driver, which fails before this change. It reuses the existing
StubDriverrather than a mock, which meant adding:helpersto theSmallTestsdeps since that stub lives in a separate target.💡 Additional Considerations
I couldn't get Bazel running locally, so I compiled the test against these sources and ran it by hand instead: it passes with this change, and fails with the original
contextcheck restored (IllegalArgumentException: Context does not provide a mechanism to execute JS). It's a plain unit test and doesn't need a browser.What that doesn't cover is the Bazel wiring, since running it that way sidesteps strict deps...so the
:helpersline is worth a glance. I followed the pattern already used by the small suite injava/test/org/openqa/selenium/interactions/BUILD.bazel.Relative locators against a
ShadowRootstill won't work, sinceShadowRootdoesn't wrap a driver. That's #13634 and needs a different approach.🔄 Types of changes