如何使用硒切换到阴影 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']"));