Intellipaat Back

Explore Courses Blog Tutorials Interview Questions
0 votes
2 views
in DevOps and Agile by (19.7k points)

I have an SVG object with a few circles and rectangle elements. Using webdriver, I can click on the main SVG object, but not any of the elements within it. The problem only seems to be with clicking (or any mouse interaction), as I can use getAttribute() to return the value(s) of width, ID, x/y, text, etc, for anything under it.

Here is an example of the HTML:

<div id="canvas">

        <svg height="840" version="1.1" width="757" xmlns="http://www.w3.org/2000/svg" style="overflow: hidden; position: relative;">

            <image x="0" y="0" width="757" height="840" preserveAspectRatio="none">

            <circle cx="272.34" cy="132.14">

            <rect x="241.47" y="139.23">

            <text style="text-anchor: middle; x="272.47" y="144.11">

        </svg>

    </div>

And an example of WebDriver trying to right-click a rectangle element (and failing):

 WebElement mapObject = driver.findElement(By.xpath("//*[name()='svg']/*[name()='rect']"));

    Actions builder = new Actions(driver);

    builder.contextClick(mapObject).perform();

But this works and returns a value:

  driver.findElement(By.xpath("//*[name()='svg']/*[name()='rect']")).getAttribute("x");    

When WebDriver errors, it's usually this:

    org.openqa.selenium.WebDriverException: '[JavaScript Error: "a.scrollIntoView is not a function" {file: "file:///var/folders/sm/jngvd6s97ldb916b7h25d57r0000gn/T/anonymous490577185394048506webdriver-profile/extensions/[email protected]/components/synthetic_mouse.js" line: 8544}]' when calling method: [wdIMouse::move]

I've spent some time researching this and it seems to be a somewhat common issue with Selenium and SVGs, however, I'm wondering if there is a workaround. The only solutions I've found are interacting with the SVG itself, which I can already do.

I'm using Selenium 2.28 (and tried 2.29) w/ Java + Firefox 17.

Any ideas greatly appreciated.

2 Answers

0 votes
by (62.9k points)

For anyone interested, I solved this in the following ways:

 

1) I was originally testing this on OSX with Firefox 17 and Selenium 2.28/29, but figured out it only works (at least for me) on Windows with Firefox 18 and Selenium 2.29

 

2) Interacting with SVGs with the standard:

driver.findElement(By.xpath(YOUR XPATH)).click();

doesn’t work. You need to use Actions.

3) to interact with SVG objects, the following XPath works:

 

"/*[name()='svg']/*[name()='SVG OBJECT']";

The SVG object being anything under the SVG element (e.g. circle, rectangle, text, etc).

 

An example of clicking an SVG object:

WebElement svgObject = driver.findElement(By.xpath(YOUR XPATH));

Actions builder = new Actions(driver);

builder.click(svgObject).build().perform();

Note: you need to call the path inside the click() function; using:

moveToElement(YOUR XPATH).click().build().perform();

It doesn’t work.

If you wish to Learn Selenium visit this Selenium Certification by Intellipaat.

0 votes
by (1.7k points)

This is a very common issue with Selenium and SVG elements, because they are often special cases due to the way in which they render inside the DOM.

The `Actions` class of Selenium sometimes gets haywire with SVG elements because they don't quite act like regular HTML elements.

Here's how you might try to workaround this problem:

Solution 1: Click Using JavaScript

Instead of using `Actions` and right click on the element you can simulate a click on SVG directly using JavaScript. This usually helps in bypassing the mouse interaction problems of the SVG elements in Selenium.

WebElement mapObject = driver.findElement(By.xpath(\"//*[name()='svg']/*[name()='rect']\"));

//Click on the svg element using JavaScript

JavascriptExecutor js = (JavascriptExecutor) driver;

js.executeScript("arguments[0].dispatchEvent(new MouseEvent('contextmenu', {bubbles: true, cancelable: true}));", mapObject);

Because SVG elements are in another XML namespace, you must use `//*[name()='rect']` so Selenium can find them. Sometimes you also need `getBoundingClientRect()` to get the element in the viewport when clicked.

WebElement mapObject = driver.findElement(By.xpath("//<.[CDATA[*[name()='svg']/*[name()='rect']]]>"));


 

Solution 3: `moveToElement` with Offset Click using `Actions`

At times, if the SVG is not scaled, then `moveToElement` with a small offset can be even more reliable to click on an SVG. Here is how you can try that too:

WebElement mapObject = driver.findElement(By.xpath("// ////*[@name()='svg']//*[@name()='rect'] \\\")); Actions actions = new Actions(driver);

// Move to the element with an offset and right-click actions.moveToElement(mapObject, 1, 1).contextClick().perform();

Explanation

- JavaScript Click: I never used the native click, because that would often reliably simulate a mouse event much better on the SVG

- Bounding Client Rect: The coordinates for the mouse event will then be more accurate, especially helpful where the item had been transformed in some fashion, such as scaled

- Move with Offset: In case the rectangle is very small, use an offset; it helps the driver see it.

This often solves issues with interaction between SVG elements with Selenium setups.

31k questions

32.8k answers

501 comments

693 users

Browse Categories

...