Selenium WebDriver: clicking on elements within an SVG using XPath

71,316

Solution 1

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, rect, 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();

doesn't work.

Solution 2

Try this workaround :

WebElement mapObject = driver.findElement(By.xpath("//*[name()='svg']/*[name()='rect']"));
((JavascriptExecutor) driver).executeScript("arguments[0].click();", mapObject);

Whenever I have too many problems with some elements while trying to click them, I use this workaround.

Solution 3

We were able to avoid the odd xpath select by doing these two things

WebElement mapObject = (WebElement) driver.executeScript('return document.querySelector(arguments[0])', "svg rect")

((JavascriptExecutor) driver).executeScript("arguments[0].dispatchEvent(new MouseEvent('click', {view: window, bubbles:true, cancelable: true}))", mapObject);

This worked on osx and phantomjs but I think it should be ok in any modern browser.

(We used the js driver so feel free to fix any compile errors)

Solution 4

Here you go:

driver.findElement(By.cssSelector("#canvas > svg > rect")).getAttribute("x") 
driver.findElement(By.cssSelector("#canvas > svg > rect")).getAttribute("y") 

This way you can do it.

Solution 5

For a JS solution:

var selector = "//*[name()='svg']/*[name()='rect']";
browser.moveToObject(selector, 5, 5);//Move to selector object with offsets.
browser.buttonPress(null);//Left-click
Share:
71,316

Related videos on Youtube

jgode
Author by

jgode

Updated on July 09, 2022

Comments

  • jgode
    jgode almost 2 years

    I have an SVG object with a few circle 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.

    • Alex Okrushko
      Alex Okrushko over 11 years
      Maybe unrelated, but why not to use driver.findElement(By.xpath("//svg/rect")).getAttribute("x")‌​;?
    • jgode
      jgode over 11 years
      Because in order to interact with an SVG via XPath in Selenium, you have to call the name() or local-name() methods. I don't know why, but, without that, it doesn't work.
  • jgode
    jgode over 11 years
    So, there's progress here. First, using JavascriptExecutor no longer throws the error I was getting in WebDriver when interacting with an SVG object. However, when I run the test, it says it clicks/hovers/etc successfully, but I don't see the interaction happen on screen. In theory, if the test successfully clicks on a rect or circle, I should see a menu pop up for the element being clicked.. but that doesn't happen, even though WebDriver says it did so. Also worth mentioning, "arguments[0].click();" didn't work for me, but .click and .click; does. P.S. Thanks for the reply.
  • Oliver Bock
    Oliver Bock over 11 years
    The XPath check using name() is necessary because SVG DOM nodes are in a different namespace.
  • Oliver Bock
    Oliver Bock over 11 years
    Also, I could get this to work in FF17.0.1, but I did need to use Actions, a straight WebElement.click() failed.
  • Mrchief
    Mrchief almost 10 years
    You don't need xpath necessarily, at least for the JS driver. It works with any element, even if you find them by CSS or Id or however.
  • Febian Shah
    Febian Shah over 9 years
    @jgode did you find a solution? I have the same problem where it executes without an error but I don't see the webpage navigate to the new page.
  • jgode
    jgode over 9 years
    @FebianShah, yes.. see my above post where I describe how I got it working in Firefox: stackoverflow.com/a/14761832/2023074 Also, it's worth noting that in IE it's possible to target SVG elements by their RaphaelID, which makes it easier. Although in my case, because I have to test SVG pages in multiple browsers, I ended up using coordinates, which I hate for automation, but it was the most stable way.
  • joaorodr84
    joaorodr84 over 8 years
    simple and effective on ChromeDriver, in Ubuntu... thanks a lot! :)
  • Sakshi Singla
    Sakshi Singla over 7 years
    I get 'Element is not clickable at point (231.1666717529297, 312.04998779296875). Other element would receive the click:' exception when I try to click on a circle in my svg. Any idea bout this?
  • jgode
    jgode over 7 years
    I'd need a little more context to understand why that doesn't work. Code, environment, etc.
  • dlauzon
    dlauzon about 5 years
    This dispatchEvent with the specified parameters is the only solution that worked for me on a deeply nested SVG <text> element.
  • spacepickle
    spacepickle over 4 years
    There is no context to this answer and, even if it answers the original question, it leaves only a new question of why this then works. Can you give some reasoning of what the answer is telling us and why it works?
  • Ashok kumar Ganesan
    Ashok kumar Ganesan over 4 years
    What is the reason that it does not work as normal tags, why this much complication for svg
  • jgode
    jgode over 4 years
    @AshokkumarGanesan this issue is from 6 years ago, so things have evolved since then with how we can interact with svgs, and how browsers treat them with regards to automation. One issue I still see sometimes, since I still test products with svgs, is, depending on how the developers have configured them, they may not be visible to the DOM. Otherwise, I don't know that the same workarounds are still necessary.
  • Ashok kumar Ganesan
    Ashok kumar Ganesan over 4 years
    Alright,is the svg is a special tag apart from div span etc.,