Selenium WebDriver: нажатие на элементы в SVG с помощью XPath
у меня есть объект SVG с несколькими элементами круга и прямоугольника. Используя webdriver, я могу нажать на основной объект svg, но не на любой из элементов внутри него. Проблема только в щелчке (или любом взаимодействии с мышью), так как я могу использовать getAttribute () для возврата значения ширины, ID, x/y, текста и т. д. Для чего-либо под ним.
вот пример 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>
и пример WebDriver, пытающегося щелкнуть правой кнопкой мыши элемент прямоугольника (и failing):
WebElement mapObject = driver.findElement(By.xpath("//*[name()='svg']/*[name()='rect']"));
Actions builder = new Actions(driver);
builder.contextClick(mapObject).perform();
но это работает и возвращает значение:
driver.findElement(By.xpath("//*[name()='svg']/*[name()='rect']")).getAttribute("x");
когда ошибки WebDriver, обычно это:
org.openqa.selenium.WebDriverException: '[JavaScript Error: "a.scrollIntoView is not a function" {file: "file:///var/folders/sm/jngvd6s97ldb916b7h25d57r0000gn/T/anonymous490577185394048506webdriver-profile/extensions/fxdriver@googlecode.com/components/synthetic_mouse.js" line: 8544}]' when calling method: [wdIMouse::move]
Я потратил некоторое время на исследование этого, и, похоже, это несколько распространенная проблема с селеном и SVGs, однако мне интересно, есть ли обходной путь. Единственные решения, которые я нашел, взаимодействуют с самим SVG, что я уже могу сделать.
Я использую Selenium 2.28 (и пробовал 2.29) с Java + Firefox 17.
любые идеи с благодарностью.
7 ответов
для тех, кто заинтересован, я решил это следующим образом:
1) я изначально тестировал это на OSX с Firefox 17 и Selenium 2.28 / 29, но понял, что он работает только (по крайней мере, для меня) на Windows с Firefox 18 и Selenium 2.29
2) взаимодействие с SVGs со стандартом:
driver.findElement(By.xpath(YOUR XPATH)).click();
не работает. Вам нужно использовать действия.
3) для взаимодействия с объектами SVG работает следующий XPath:
"/*[name()='svg']/*[name()='SVG OBJECT']";
в СВГ объект, являющийся чем-либо под элементом SVG (например, circle, rect, text и т. д.).
пример нажатия на объект SVG:
WebElement svgObject = driver.findElement(By.xpath(YOUR XPATH));
Actions builder = new Actions(driver);
builder.click(svgObject).build().perform();
Примечание: вам нужно вызвать путь внутри функции click (); используя:
moveToElement(YOUR XPATH).click().build().perform();
не работает.
попробуйте этот метод :
WebElement mapObject = driver.findElement(By.xpath("//*[name()='svg']/*[name()='rect']"));
((JavascriptExecutor) driver).executeScript("arguments[0].click();", mapObject);
когда у меня слишком много проблем с некоторыми элементами, при попытке нажать их, я использую этот способ.
мы смогли избежать нечетного выбора xpath, выполнив эти две вещи
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);
это работало на osx и phantomjs, но я думаю, что это должно быть нормально в любом современном браузере.
(мы использовали драйвер js, поэтому не стесняйтесь исправлять любые ошибки компиляции)
здесь вы идете:
driver.findElement(By.cssSelector("#canvas > svg > rect")).getAttribute("x")
driver.findElement(By.cssSelector("#canvas > svg > rect")).getAttribute("y")
таким образом, вы можете сделать это.
У меня есть разные высокие диаграммы в моем проекте, и моя цель состояла в том, чтобы дважды щелкнуть по разделу диаграммы для детализации для получения дополнительной информации, и мне удалось сделать это, используя следующие строки кода. XPath не работал для меня, но CssSelector работал отлично.
var elementToClick= Browser.Driver.FindElementEx(By.CssSelector("#highcharts-0 > svg > g.highcharts-series-group > g.highcharts-series.highcharts-tracker > path:nth-child(1)"), 10);
Actions action = new Actions(Browser.Driver);
action.Click(elementToClick).Build().Perform();
action.DoubleClick(elementToClick).Build().Perform();
для решения JS:
var selector = "//*[name()='svg']/*[name()='rect']";
browser.moveToObject(selector, 5, 5);//Move to selector object with offsets.
browser.buttonPress(null);//Left-click
вот пример обходного пути в C#:
IWebElement svgElement = Driver.FindElement(By.CssSelector("svg"));
IList<IWebElement> rectElements = svgElement.FindElements(By.CssSelector("rect"));