Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[🐛 Bug]: (Java) S3-S4 W3C Mode Not Supported Using RemoteWebElement to getLocation and getSize #10698

Closed
BJap opened this issue May 26, 2022 · 4 comments · Fixed by #10700
Closed

Comments

@BJap
Copy link
Contributor

BJap commented May 26, 2022

What happened?

When the user attempts to get a web element's location and size, the code will crash because the command is not supported in W3C mode.

This is due to the fact that unlike JWP, those commands are not supported, and W3C only allows getRect as per spec.

https://w3c.github.io/webdriver/#get-element-rect

Only JWP (not W3C) allows those two as supported commands:

https://www.selenium.dev/documentation/legacy/json_wire_protocol/#sessionsessionidelementidlocation
https://www.selenium.dev/documentation/legacy/json_wire_protocol/#sessionsessionidelementidsize

The code in Selenium 3 should have checked for W3C mode like the Python implementation does, and choose accordingly. Selenium 4 is W3C mode purely and the code should have been migrated to support only that. It is currently still using JWP commands.

This means that the Python and Java implementations are not in sync, and the Java implementation is incorrect. The getLocation and getSize code for Selenium 4 could just use the getRect as a function in both implementations since that's all that's available, and wrap around it to extract the relevant data.

Java

Python

Screen Shot 2022-05-25 at 13 37 53

---

Screen Shot 2022-05-25 at 13 41 57

The solution for Selenium 4 Java (and similarly Python) can just be something like:

@Override
@SuppressWarnings({"unchecked"})
public Point getLocation() {
  Rectangle rect = getRect();
  return rect.getPoint();
}

@Override
@SuppressWarnings({"unchecked"})
public Dimension getSize() {
  Rectangle rect = getRect();
  return rect.getDimension();
}

@Override
@SuppressWarnings({"unchecked"})
public Rectangle getRect() {
  Response response = execute(DriverCommand.GET_ELEMENT_RECT(id));
  Map<String, Object> rawRect = (Map<String, Object>) response.getValue();
  int x = ((Number) rawRect.get("x")).intValue();
  int y = ((Number) rawRect.get("y")).intValue();
  int width = ((Number) rawRect.get("width")).intValue();
  int height = ((Number) rawRect.get("height")).intValue();
  return new Rectangle(x, y, height, width);
}

or for consistency, this:

@Override
@SuppressWarnings({"unchecked"})
public Point getLocation() {
  Response response = execute(DriverCommand.GET_ELEMENT_RECT(id));
  Map<String, Object> rawPoint = (Map<String, Object>) response.getValue();
  int x = ((Number) rawPoint.get("x")).intValue();
  int y = ((Number) rawPoint.get("y")).intValue();
  return new Point(x, y);
}

@Override
@SuppressWarnings({"unchecked"})
public Dimension getSize() {
  Response response = execute(DriverCommand.GET_ELEMENT_RECT(id));
  Map<String, Object> rawSize = (Map<String, Object>) response.getValue();
  int width = ((Number) rawSize.get("width")).intValue();
  int height = ((Number) rawSize.get("height")).intValue();
  return new Dimension(width, height);
}

@Override
@SuppressWarnings({"unchecked"})
public Rectangle getRect() {
  Response response = execute(DriverCommand.GET_ELEMENT_RECT(id));
  Map<String, Object> rawRect = (Map<String, Object>) response.getValue();
  int x = ((Number) rawRect.get("x")).intValue();
  int y = ((Number) rawRect.get("y")).intValue();
  int width = ((Number) rawRect.get("width")).intValue();
  int height = ((Number) rawRect.get("height")).intValue();
  return new Rectangle(x, y, height, width);
}

In Selenium 3 this was a parameterized choice of one or the other based on whether the test was run in JWP or W3C modes. in Selenium 4, those two functions are basically just helper/wrapper functions.

How can we reproduce the issue?

Visit a webpage (Selenium) or a WebView (Appium) in W3C mode, and attempt to get the size or location of a WebElement.

webElement.getLocation();

webElement.getSize();

The workaround is to use the API directly as the fix above would suggest and use:

webElement.getRect().getPoint();

webElement.getRect().getDimension();

The problem with this is that a lot of teams that are using this for their testing and want to migrate already have much of their code written in the former use case. It would ease the friction of migration and save lost hours of debugging time to correct the implementation and allow teams to use their code in its existing state without the workaround.

Relevant log output

Description: "Cannot call non W3C standard command while in W3C mode "

When using getLocation()

at org.openqa.selenium.remote.http.W3CHttpResponseCodec.createException(W3CHttpResponseCodec.java:187)
at org.openqa.selenium.remote.http.W3CHttpResponseCodec.decode(W3CHttpResponseCodec.java:122)
at org.openqa.selenium.remote.http.W3CHttpResponseCodec.decode(W3CHttpResponseCodec.java:49)
at org.openqa.selenium.remote.HttpCommandExecutor.execute(HttpCommandExecutor.java:158)
at io.appium.java_client.remote.AppiumCommandExecutor.execute(AppiumCommandExecutor.java:250)
at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:552)
at io.appium.java_client.DefaultGenericMobileDriver.execute(DefaultGenericMobileDriver.java:41)
at io.appium.java_client.AppiumDriver.execute(AppiumDriver.java:1)
at io.appium.java_client.android.AndroidDriver.execute(AndroidDriver.java:1)
at org.openqa.selenium.remote.RemoteWebElement.execute(RemoteWebElement.java:285)
at io.appium.java_client.DefaultGenericMobileElement.execute(DefaultGenericMobileElement.java:45)
at io.appium.java_client.MobileElement.execute(MobileElement.java:1)
at io.appium.java_client.android.AndroidElement.execute(AndroidElement.java:1)
at org.openqa.selenium.remote.RemoteWebElement.getLocation(RemoteWebElement.java:337)

--

When using getSize()

at org.openqa.selenium.remote.http.W3CHttpResponseCodec.createException(W3CHttpResponseCodec.java:187)
at org.openqa.selenium.remote.http.W3CHttpResponseCodec.decode(W3CHttpResponseCodec.java:122)
at org.openqa.selenium.remote.http.W3CHttpResponseCodec.decode(W3CHttpResponseCodec.java:49)
at org.openqa.selenium.remote.HttpCommandExecutor.execute(HttpCommandExecutor.java:158)
at io.appium.java_client.remote.AppiumCommandExecutor.execute(AppiumCommandExecutor.java:250)
at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:552)
at io.appium.java_client.DefaultGenericMobileDriver.execute(DefaultGenericMobileDriver.java:41)
at io.appium.java_client.AppiumDriver.execute(AppiumDriver.java:1)
at io.appium.java_client.android.AndroidDriver.execute(AndroidDriver.java:1)
at org.openqa.selenium.remote.RemoteWebElement.execute(RemoteWebElement.java:285)
at io.appium.java_client.DefaultGenericMobileElement.execute(DefaultGenericMobileElement.java:45)
at io.appium.java_client.MobileElement.execute(MobileElement.java:1)
at io.appium.java_client.android.AndroidElement.execute(AndroidElement.java:1)
at org.openqa.selenium.remote.RemoteWebElement.getSize(RemoteWebElement.java:346)

Operating System

Not Applicable but on macOS against Android and iOS

Selenium version

Java Selenium 3 and 4

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

WebView

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

Available on Request

Are you using Selenium Grid?

No

@github-actions
Copy link

@BJap, 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!

@diemol
Copy link
Member

diemol commented May 26, 2022

That makes sense, thanks for raising this, @BJap. This should go together with #10374. Would you like to send a PR with that change you are proposing?

@BJap
Copy link
Contributor Author

BJap commented May 26, 2022

@diemol I checked with my team and I can do that. Let me go and open one now.

BJap added a commit to BJap/selenium that referenced this issue May 26, 2022
diemol pushed a commit that referenced this issue May 27, 2022
…tandard to W3C Standard (#10700)

* [Java] Convert RemoteWebElement::getLocation and ::getSize from JWP Standard to W3C Standard

Fixes #10698 as part of #10374

* [java] Fixing RemoteWebElementTest unit tests

Co-authored-by: Diego Molina <[email protected]>
Co-authored-by: Diego Molina <[email protected]>

[skip ci]
@github-actions
Copy link

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.

@github-actions github-actions bot locked and limited conversation to collaborators Jun 27, 2022
elgatov pushed a commit to elgatov/selenium that referenced this issue Jun 27, 2022
…tandard to W3C Standard (SeleniumHQ#10700)

* [Java] Convert RemoteWebElement::getLocation and ::getSize from JWP Standard to W3C Standard

Fixes SeleniumHQ#10698 as part of SeleniumHQ#10374

* [java] Fixing RemoteWebElementTest unit tests

Co-authored-by: Diego Molina <[email protected]>
Co-authored-by: Diego Molina <[email protected]>

[skip ci]
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
2 participants