如何使用硒切换到阴影 dom 内的 iframe
How to switch to iframe inside shadow dom with selenium
被测应用程序基于 Electron(版本 9.1.1)编写为 Linux 的桌面应用程序。
在电子中有自定义标签 <webview>
即引用 "The webview tag is essentially a custom element using shadow DOM to wrap an iframe element inside it."
我可以访问阴影 dom 并使用 Java selenim(版本 3.141.59)从中获取 iframe 作为 WebElement
。
但是切换到 iframe 仍然让我停留在父上下文中。
我的问题是:
如何切换到 IFRAME INSIDE SHADOW DOM?
//getting webdriver
WebDriver driver = WebDriverRunner.getWebDriver();
JavascriptExecutor js = (JavascriptExecutor) driver;
//acquire shadow dom WebElement
WebElement shadowDom = (WebElement) js.executeScript("return arguments[0].shadowRoot", driver.findElement(By.tagName("webview")));
//acquire iframe WebElement
WebElement iframe = shadowDom.findElement(By.tagName("iframe"));
//trying to swith to iframe inside shadow DOM, but still at parent context because can't find element that exist in iframe
driver.switchTo().frame(iframe);
//obviously produce NoSuchElementException
driver.findElement(By.xpath(".//label[text()='Columns']"));
这是页面的 HTML,我可以在 devtools 命令中执行 webview
的 html document.querySelector('webview').openDevTools();
这就是为什么我确定 .//label[text()='Columns']
存在。
UPD 我正在通过公开端口连接到电子应用程序,也许这是个问题?
public WebDriver createDriver(DesiredCapabilities desiredCapabilities)
ChromeOptions options = new ChromeOptions();
options.setExperimentalOption("debuggerAddress", "localhost:8315");
options.setAcceptInsecureCerts(true);
options.merge(desiredCapabilities);
return new ChromeDriver(options);
}
其实答案很简单。您只需要明确声明您希望 webview 出现在 window 句柄列表中。
这是官方的 chromedriver 文档 link 功能名称是 windowTypes
在 java 代码中看起来像这样
ChromeOptions options = new ChromeOptions();
List<String> webview = Collections.singletonList("webview");
options.setExperimentalOption("windowTypes", webview);
WebDriver driver = new ChromeDriver(options);
//after that you can just switch to is
driver.switchTo().window("yourHandle");
//and work with it as usual
driver.findElement(By.xpath(".//label[text()='Columns']"));
被测应用程序基于 Electron(版本 9.1.1)编写为 Linux 的桌面应用程序。
在电子中有自定义标签 <webview>
即引用 "The webview tag is essentially a custom element using shadow DOM to wrap an iframe element inside it."
我可以访问阴影 dom 并使用 Java selenim(版本 3.141.59)从中获取 iframe 作为 WebElement
。
但是切换到 iframe 仍然让我停留在父上下文中。
我的问题是:
如何切换到 IFRAME INSIDE SHADOW DOM?
//getting webdriver
WebDriver driver = WebDriverRunner.getWebDriver();
JavascriptExecutor js = (JavascriptExecutor) driver;
//acquire shadow dom WebElement
WebElement shadowDom = (WebElement) js.executeScript("return arguments[0].shadowRoot", driver.findElement(By.tagName("webview")));
//acquire iframe WebElement
WebElement iframe = shadowDom.findElement(By.tagName("iframe"));
//trying to swith to iframe inside shadow DOM, but still at parent context because can't find element that exist in iframe
driver.switchTo().frame(iframe);
//obviously produce NoSuchElementException
driver.findElement(By.xpath(".//label[text()='Columns']"));
这是页面的 HTML,我可以在 devtools 命令中执行 webview
的 html document.querySelector('webview').openDevTools();
这就是为什么我确定 .//label[text()='Columns']
存在。
UPD 我正在通过公开端口连接到电子应用程序,也许这是个问题?
public WebDriver createDriver(DesiredCapabilities desiredCapabilities)
ChromeOptions options = new ChromeOptions();
options.setExperimentalOption("debuggerAddress", "localhost:8315");
options.setAcceptInsecureCerts(true);
options.merge(desiredCapabilities);
return new ChromeDriver(options);
}
其实答案很简单。您只需要明确声明您希望 webview 出现在 window 句柄列表中。
这是官方的 chromedriver 文档 link 功能名称是 windowTypes
在 java 代码中看起来像这样
ChromeOptions options = new ChromeOptions();
List<String> webview = Collections.singletonList("webview");
options.setExperimentalOption("windowTypes", webview);
WebDriver driver = new ChromeDriver(options);
//after that you can just switch to is
driver.switchTo().window("yourHandle");
//and work with it as usual
driver.findElement(By.xpath(".//label[text()='Columns']"));