【问题标题】:How do I get Selenium Java to click on an SVG Node in an SVG DOM Tree?如何让 Selenium Java 单击 SVG DOM 树中的 SVG 节点?
【发布时间】:2018-08-30 18:49:45
【问题描述】:

我正在尝试使用 SVG 节点自动化测试。我需要点击一个特定的节点。

我在 Firefox 中单击该元素,单击 F12 以启动控制台,然后键入 console.dir($0) 以查看详细信息。这是元素的样子:

text
​
__data__: Object { height: 0, depth: 1, x: 0, … }
​
attributes: NamedNodeMap [ fill="#fff", font-size="36px", font-family="mapicons", … ]
​
baseURI: "https://fnord.co.uk/#/jobs/add/job?@=-702x6714391y19z&lf=1!19.73740"
​
childElementCount: 0
​
childNodes: NodeList [ #text ]
​
children: HTMLCollection []
​
classList: DOMTokenList []
​
className: SVGAnimatedString { baseVal: "", animVal: "" }
​
clientHeight: 0
​
clientLeft: 0
​
clientTop: 0
​
clientWidth: 0
​
dataset: DOMStringMap {  }
​
dx: SVGAnimatedLengthList { baseVal: SVGLengthList, animVal: SVGLengthList }
​
dy: SVGAnimatedLengthList { baseVal: SVGLengthList, animVal: SVGLengthList }
​
farthestViewportElement: <svg id="svgstruct" style="position: relative; overflow: visible; margin-top: 50px; margin-left: 20px; min-width: 100%;" width="100%" height="100%">
​
firstChild: #text ""
​
firstElementChild: null
​
id: ""
​
innerHTML: "\ue05e"
​
isConnected: true
​
lastChild: #text ""
​
lastElementChild: null
​
lengthAdjust: SVGAnimatedEnumeration { baseVal: 1, animVal: 1 }
​
localName: "text"
​
namespaceURI: "http://www.w3.org/2000/svg"
​
nearestViewportElement: <svg id="svgstruct" style="position: relative; overflow: visible; margin-top: 50px; margin-left: 20px; min-width: 100%;" width="100%" height="100%">
​
nextElementSibling: null
​
nextSibling: null
​
nodeName: "text"
​
nodeType: 1
​
nodeValue: null
​
onabort: null
​
onanimationcancel: null
​
onanimationend: null
​
onanimationiteration: null
​
onanimationstart: null
​
onauxclick: null
​
onblur: null
​
oncanplay: null
​
oncanplaythrough: null
​
onchange: null
​
onclick: null
​
onclose: null
​
oncontextmenu: null
​
oncopy: null
​
oncut: null
​
ondblclick: null
​
ondrag: null
​
ondragend: null
​
ondragenter: null
​
ondragexit: null
​
ondragleave: null
​
ondragover: null
​
ondragstart: null
​
ondrop: null
​
ondurationchange: null
​
onemptied: null
​
onended: null
​
onerror: null
​
onfocus: null
​
ongotpointercapture: null
​
oninput: null
​
oninvalid: null
​
onkeydown: null
​
onkeypress: null
​
onkeyup: null
​
onload: null
​
onloadeddata: null
​
onloadedmetadata: null
​
onloadend: null
​
onloadstart: null
​
onlostpointercapture: null
​
onmousedown: null
​
onmouseenter: null
​
onmouseleave: null
​
onmousemove: null
​
onmouseout: null
​
onmouseover: null
​
onmouseup: null
​
onmozfullscreenchange: null
​
onmozfullscreenerror: null
​
onpaste: null
​
onpause: null
​
onplay: null
​
onplaying: null
​
onpointercancel: null
​
onpointerdown: null
​
onpointerenter: null
​
onpointerleave: null
​
onpointermove: null
​
onpointerout: null
​
onpointerover: null
​
onpointerup: null
​
onprogress: null
​
onratechange: null
​
onreset: null
​
onresize: null
​
onscroll: null
​
onseeked: null
​
onseeking: null
​
onselect: null
​
onselectstart: null
​
onshow: null
​
onstalled: null
​
onsubmit: null
​
onsuspend: null
​
ontimeupdate: null
​
ontoggle: null
​
ontransitioncancel: null
​
ontransitionend: null
​
ontransitionrun: null
​
ontransitionstart: null
​
onvolumechange: null
​
onwaiting: null
​
onwebkitanimationend: null
​
onwebkitanimationiteration: null
​
onwebkitanimationstart: null
​
onwebkittransitionend: null
​
onwheel: null
​
outerHTML: "<text fill=\"#fff\" font-size=\"36px\" font-family=\"mapicons\" transform=\"translate(0,30)\">\ue05e</text>"
​
ownerDocument: HTMLDocument https://alloy-labs.yotta.co.uk/#/jobs/add/job?@=-702x6714391y19z&lf=1!19.73740
​
ownerSVGElement: <svg id="svgstruct" style="position: relative; overflow: visible; margin-top: 50px; margin-left: 20px; min-width: 100%;" width="100%" height="100%">
​
parentElement: <g class="node" cursor="pointer" transform="translate(30,110)">
​
parentNode: <g class="node" cursor="pointer" transform="translate(30,110)">
​
prefix: null
​
previousElementSibling: <path d="M0,0a30,30,0,1,0,0,60h0a30,30,0,1,0,0,-60Z" fill="#f5c041">
​
previousSibling: <path d="M0,0a30,30,0,1,0,0,60h0a30,30,0,1,0,0,-60Z" fill="#f5c041">
​
requiredExtensions: SVGStringList { length: 0, numberOfItems: 0 }
​
requiredFeatures: SVGStringList { length: 0, numberOfItems: 0 }
​
rotate: SVGAnimatedNumberList { baseVal: SVGNumberList, animVal: SVGNumberList }
​
scrollHeight: 0
​
scrollLeft: 0
​
scrollLeftMax: 0
​
scrollTop: 0
​
scrollTopMax: 0
​
scrollWidth: 0
​
style: CSS2Properties {  }
​
systemLanguage: SVGStringList { length: 0, numberOfItems: 0 }
​
tabIndex: -1
​
tagName: "text"
​
textContent: "\ue05e"
​
textLength: SVGAnimatedLength { baseVal: SVGLength, animVal: SVGLength }
​
transform: SVGAnimatedTransformList { baseVal: SVGTransformList […], animVal: SVGTransformList […] }
​
viewportElement: <svg id="svgstruct" style="position: relative; overflow: visible; margin-top: 50px; margin-left: 20px; min-width: 100%;" width="100%" height="100%">
​
x: SVGAnimatedLengthList { baseVal: SVGLengthList, animVal: SVGLengthList }
​
y: SVGAnimatedLengthList
​​
animVal: SVGLengthList { numberOfItems: 0, length: 0 }
​​
baseVal: SVGLengthList
​​​
length: 0
​​​
numberOfItems: 0
​​​
__proto__: SVGLengthListPrototype { clear: clear(), initialize: initialize(), getItem: getItem(), … }
​​
__proto__: SVGAnimatedLengthListPrototype { baseVal: Getter, animVal: Getter, … }
​
__proto__: SVGTextElementPrototype
​​
constructor: ()
​​​
length: 0
​​​
name: "SVGTextElement"
​​​
prototype: SVGTextElementPrototype { … }
​​​
Symbol(Symbol.hasInstance): undefined
​​​
__proto__: function ()
​​
__proto__: SVGTextPositioningElementPrototype

我尝试使用按类名查找,但没有成功:

String className="SVGAnimatedString";
        List<WebElement> cardTitles = driver.findElements(By.className(className));

显然className不代表这种className?

所以我尝试使用 cssSelector 找到它。这可行,但不太有用,因为每次屏幕加载时 CSS 选择器都会更改。 找到我的元素后,如果我只使用 element.click 单击它,则不会发生任何事情。 如果我使用这个 Javascript 点击它,它会抛出一个异常:

JavascriptExecutor executor = (JavascriptExecutor) driver;
            executor.executeScript("arguments[0].click();", element);

异常信息:

org.openqa.selenium.JavascriptException: TypeError: arguments[0].click 不是函数

如何让点击在此元素上起作用?

这不是 Selenium WebDriver [Java]: How to Click on elements within an SVG using XPath 的副本

与那个询问者不同,我设法找到了我的元素。

我的问题是点击那个元素。

浏览器:Firefox Quantum 59.0.1(64 位) 壁虎司机:0.19.1 硒罐:3.8.1

【问题讨论】:

标签: javascript java css selenium svg


【解决方案1】:

我认为你的 find by 是错误的。还有很多东西要添加到这篇文章中来帮助调试。

  1. 什么版本的 firefox、webdriver(firefox、marionetter 或 gecko) 你在用硒罐吗?
  2. 它是否可以在其他浏览器中使用?

回应:
显然className不代表这种className

您可以从控制台检查您的查找语法,因此在您的情况下键入以下内容以查找具有 SVGAnimatedString 类的元素:

$('.SVGAnimatedString')

单击折叠箭头查看是否找到任何内容。

从您发布的属性中,您的元素没有设置任何类值:

classList: DOMTokenList []

在这个网站https://demos.telerik.com/kendo-ui/dragdrop/events
点击大圆圈并重复

console.dir($0)  
classList: DOMTokenList [ "k-header" ]

这是 DOM 中的元素

<div id="droptarget" class="k-header" data-role="droptarget">Drag the small circle here.</div>

因此这些 CSS 选择器可以工作:

$('.k-header') ==> finds 6, class only
$('div.k-header')  ==> finds 4, element type and class
$('div.k-header[data-role="droptarget"]') ===> finds 1, as above with attribute and value

你需要使用什么 CSS 选择器?

我注意到发布的属性也有:

clientHeight: 0
​clientLeft: 0
clientTop: 0
clientWidth: 0

​ 所以看起来你有一个隐藏的元素?

我的建议是单击元素,将其显示在 DOM 中,然后尝试在您正在使用的元素之上或之下的几个元素,您可能会发现这些元素具有稳定的属性,使其更容易。

您还可以使用此代码仔细检查您的 webdriver 和 selenium 认为元素在哪里(更新以创建驱动程序):

 WebDriver webDriver = new FireFoxDriver();
 Actions actions = new Actions(webDriver);
 webDriver.navigate().to("https://demos.telerik.com/kendo-ui/dragdrop/events");
 Thread.sleep(500);
 WebElement drop = webDriver.findElement(By.cssSelector("#droptarget"));
 //movetoelement should be center and is
 actions.moveToElement(drop).contextClick().perform();
 Thread.sleep(500);
 webDriver.quit();

我使用过 SVG 元素并且正常的 .click() 工作正常: Firefox 57.0.2、57.0.3、58.0.2、59.0 与 geckodriver 0.18.0 和 selenium-java:3.7.1

【讨论】:

  • 我尝试在控制台输入 $('.SVGAnimatedString')。得到这个响应: $('.SVGAnimatedString') {…} 长度:0 ​ prevObject: Object [ HTMLDocument fnord.co.uk/#/jobs/add/job?@=-736x6714468y19z&lf=1!19.73740 ] proto: Object { jquery: "3.1.1", constructor: r(), 长度: 0, ... }
  • 您的代码已经右键单击我的元素? actions.moveToElement(drop).contextClick().perform();
  • @SteveStaple 对于您的第一条评论:控制台检查只是一种快速确认您的元素无法使用原始类模式找到的方法 - 长度:0 表示没有找到。您是否尝试过我上面答案中的demos.telerik.com/kendo-ui/dragdrop/events 示例 - 这样您就可以更好地了解按班级查找?根据答案,您现在使用什么来查找元素?我的示例代码应该进行右键单击,它旨在显示触发右键单击事件时鼠标的位置。尝试用 click() 替换 contextClick()。
  • 我这样做了 - 将 contextClick 替换为 click。它似乎可以工作(即:它继续执行下一条语句并且没有抛出异常)。
  • @SteveStaple 好的,因此您可以使用鼠标单击而不是普通的 WebElement.click() 来获得解决方案。如果您想使用普通的 WebElement.click() ,请查看我上面的原始建议,探索您当前找到的元素上方和下方的 DOM 元素,使用控制台搜索仔细检查您的选择器返回的内容(就像您使用 $ ('.SVGAnimatedString')和我的剑道网站示例)。如果您对解决方案感到满意,请考虑接受我的回答。
【解决方案2】:

如果类名有一些永远不会改变的东西,你可以使用这样的东西。部分搜索将是一个简单的解释:

targetElement.findElement(By.cssSelector("[className*='partialClassNameString']"));

“*”表示您要匹配此字符串或此字符串作为任何具有 className 属性的 Web 元素的子字符串。

就点击元素而言。您是否尝试过使用提交?我在这里抓住了稻草,但尝试并没有什么坏处。而不是 .click() 你使用 .submit()

【讨论】:

    猜你喜欢
    • 2020-12-22
    • 2019-11-26
    • 2023-01-18
    • 2012-06-27
    • 2017-06-09
    • 2014-12-24
    • 2020-04-05
    • 2021-09-14
    相关资源
    最近更新 更多