如何解决如何定位 Selenium 中 Shadow DOM 中存在的 svg 元素
我可以使用 JS Path 或使用 sukgu (https://github.com/sukgu/shadow-automation-selenium) 创建的插件来定位 svg 以外的元素
问题在于 Shadow 根中存在 svg 元素,我无法找到它。 尝试了以下方法:
-
在尝试使用 css 选择器查找 svg 元素时,出现以下错误:-
WebElement ele = (WebElement) js.executeScript("return document.querySelector(\"body > sn-component-va-web-client\").shadowRoot.querySelector(\"#Path\")"); ele.click();
输出 -
org.openqa.selenium.ElementClickInterceptedException:元素点击 截取:元素
-
使用上述插件查找 svg - 使用 css 选择器
WebElement close = shadow.findElement("div > div.sn-cs-header > div.header-menu > div.menu-item.new-conversation-clicker > div.new-conversation-button > div > svg"); close.click();
输出 -
org.openqa.selenium.ElementNotVisibleException:带有 CSS div 的元素 > div.sn-cs-header > div.header-菜单 > div.menu-item.new-conversation-clicker > div.new-conversation-button > div > svg 不在屏幕上
-
使用 Xpath
WebElement close = shadow.findElementByXPath("//*[local-name()='svg']//g//g//g//path[@id='Path']"); close.click();
输出 -
org.openqa.selenium.ElementNotVisibleException:带有 XPath 的元素 //*[local-name()='svg']//g//g//g//path[@id='Path'] 不存在于 屏幕
以下是 HTML :-
<div class="conversation-container" style="display: block;">
<iframe title="Chat Support" id="myiFrame" class="chat-frame" scrolling="no" horizontalscrolling="no" verticalscrolling="no" frameborder="none" ng-src="/$sn-va-web-client-app.do?sysparm_nostack=true&sysparm_stack=no" src="/$sn-va-web-client-app.do?sysparm_nostack=true&sysparm_stack=no"></iframe>
</div>
<iframe title="Chat Support" id="myiFrame" class="chat-frame" scrolling="no" horizontalscrolling="no" verticalscrolling="no" frameborder="none" ng-src="/$sn-va-web-client-app.do?sysparm_nostack=true&sysparm_stack=no" src="/$sn-va-web-client-app.do?sysparm_nostack=true&sysparm_stack=no"></iframe>
#document
<html>
<head>
<body>
<sn-component-va-web-client component-id="cid1" now-id="cid1"></sn-component-va-web-client>
#shadow-root (open)
<div class="sn-cs-webclient fill-window text-direction-ltr">
<div class="sn-cs-accessibility-reader" aria-live="polite" aria-atomic="false"></div>
<div></div>
<div class="sn-cs-header" style="z-index: 500;">
<div class="chat-title">
<div class="header-circle">
<img class="header-icon " src="599c06dedbbe6c109005db184b961967.iix" alt="Header Icon">
</div>
</div>
<div class="header-menu">
<div class="menu-item new-conversation-clicker " aria-label="End conversation" aria-haspopup="menu" role="button" aria-describedby="new-conversation-tip" tabindex="0">
<div class="new-conversation-button">
<div class="new-convo-icon close-icon">
<svg viewBox="0 0 26 23" version="1.1"
xmlns="http://www.w3.org/2000/svg">
<g id="Symbols" stroke="none" stroke-width="1" fill="rgba(0,0)" fill-rule="evenodd">
<g id="header/New-header-la-no-name" transform="translate(-330.000000,-20.000000)" fill-rule="nonzero" stroke="#ffffff" stroke-width="2">
<g id="Group" transform="translate(329.000000,20.000000)">
<path d="M13.55,1 C7.17042969,1
<!-- removed extra numbers --> 19.9295703,1 13.55,1 Z" id="Path">
</path>
</g>
</g>
</g>
</svg>
解决方法
请尝试以下操作:
WebElement root = driver.findElement(By.cssSelector("body > sn-component-va-web-client"));
WebElement shadow_root = expand_shadow_element(root);
WebElement path = shadow_root.findElement(By.cssSelector("g > g > path"));
path.click();
public static WebElement expand_shadow_element(WebElement element)
{
WebElement shadow_root = (WebElement)((JavascriptExecutor)driver).executeScript("return arguments[0].shadowRoot",element);
return shadow_root;
}
感谢 author
,我想问题是 svg 元素所在的命名空间不同。 看看这里:https://www.inflectra.com/support/knowledgebase/kb503.aspx
所以可能你需要(如果 g 元素不相关):
//*[local-name()='svg']//*[local-name()='path' and @id='Path']
如果 g 元素是相关的,您需要:
//*[local-name()='svg']/*[local-name()='g']/*[local-name()='g']/*[local-name()='g']/*[local-name()='path' and @id='Path']
或者甚至可以像这样使用 XPath id 函数:
id('Path')
,
我能够通过变通方法定位/单击 svg 元素,而不是找到 svg 元素的 xpath,我尝试在 svg 之前定位该元素。
步骤:-
识别并点击 svg 元素之前的非 svg 元素
import os,strutils
template innerLoop(it,op: untyped): untyped =
for file {.inject.} in it:
if toLower(op).endsWith(suffix):
return true
proc containsFilesWithSuffix(dir: string,suffix: string,recursive: bool = true) : bool =
if recursive:
innerLoop(walkDirRec(dir),file)
else:
innerLoop(walkDir(dir),file.path)
return false
使用操作类将焦点移动到 svg 元素并点击它
Shadow shadow = new Shadow(driver); // Using sukgu plugin
WebElement x = shadow.findElementByXPath("xpath");
x.click();
,
任何答案都将是一个成功的尝试,而无需实际查看 DOM。 ShadowDOM 通常很棘手。
如果您经常在这些方面遇到困难,我建议您安装并使用 Chrome 的 Selectorshub 扩展:https://chrome.google.com/webstore/detail/selectorshub/ndgimibanhlabgdgjcpbbndiehljcpfh?hl=en
安装后,请查看此链接以了解如何为 shadow dom 正确路径: https://www.youtube.com/watch?v=SCOAS86rJ9E
它具有许多其他功能,可让您快速编写路径。用于 ui 自动化目的的非常好的扩展 imo。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。