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, пытающийся щелкнуть правой кнопкой мыши элемент прямоугольника (и не выполнить):
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/[email protected]/components/synthetic_mouse.js" line: 8544}]' when calling method: [wdIMouse::move]
Я потратил некоторое время на исследование этого вопроса, и это, похоже, является довольно распространенной проблемой для Selenium и SVG, однако мне интересно, есть ли способ обхода проблемы. Единственные решения, которые я нашел, взаимодействуют с самим SVG, что я уже могу сделать.
Я использую Selenium 2.28 (и пробовал 2.29) с Java + Firefox 17.
Любые идеи получили высокую оценку.
Ответы
Ответ 1
Для всех, кого это интересует, я решил это следующим образом:
1) Я первоначально тестировал это на OSX с Firefox 17 и Selenium 2.28/29, но понял, что он работает только (по крайней мере для меня) в Windows с Firefox 18 и Selenium 2.29
2), взаимодействующий с SVG со стандартом:
driver.findElement(By.xpath(YOUR XPATH)).click();
не работает. Вам нужно использовать Actions.
3), чтобы взаимодействовать с объектами SVG, работает следующий XPath:
"/*[name()='svg']/*[name()='SVG OBJECT']";
Объект SVG представляет собой что-либо под элементом SVG (например, круг, прямоугольник, текст и т.д.).
Пример нажатия на объект 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();
не работает.
Ответ 2
Попробуйте обходное решение:
WebElement mapObject = driver.findElement(By.xpath("//*[name()='svg']/*[name()='rect']"));
((JavascriptExecutor) driver).executeScript("arguments[0].click();", mapObject);
Всякий раз, когда у меня слишком много проблем с некоторыми элементами при попытке щелкнуть их, я использую это обходное решение.
Ответ 3
Нам удалось избежать выбора нечетного 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, поэтому не стесняйтесь исправить ошибки компиляции)
Ответ 4
Здесь вы идете:
driver.findElement(By.cssSelector("#canvas > svg > rect")).getAttribute("x")
driver.findElement(By.cssSelector("#canvas > svg > rect")).getAttribute("y")
Таким образом вы можете это сделать.
Ответ 5
У меня разные графические диаграммы в моем проекте, и моя цель состояла в том, чтобы дважды щелкнуть по разделу диаграммы, чтобы развернуть дополнительную информацию, и мне удалось это сделать, используя следующие строки кода.
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();
Ответ 6
Для решения JS:
var selector = "//*[name()='svg']/*[name()='rect']";
browser.moveToObject(selector, 5, 5);//Move to selector object with offsets.
browser.buttonPress(null);//Left-click
Ответ 7
Вот пример обходного пути в С#:
IWebElement svgElement = Driver.FindElement(By.CssSelector("svg"));
IList<IWebElement> rectElements = svgElement.FindElements(By.CssSelector("rect"));
Ответ 8
actual = driver.findElement(By.xpath(
"//div[contains(@class,'review-action')]//div[contains(@class,'rating')]/*[name()='svg'][1]/*[name()='g']/*[name()='path'][2]"))
.getAttribute("stroke");