javaselenium-webdrivertestingautomation

Exception in thread "main" java.lang.ClassCastException: class org.openqa.selenium.remote.ShadowRoot cannot be cast to class org.openqa.selenium.Web


I had tried to write this program for Shadow DOM in selenium but I am getting this error. Any solutions as to how I can rectify this error.

Tried different ways to rewrite the code and find where the error persists but still error occurs.

Exception

Exception in thread "main" java.lang.ClassCastException: class org.openqa.selenium.remote.ShadowRoot cannot be cast to class org.openqa.selenium.WebElement (org.openqa.selenium.remote.ShadowRoot and org.openqa.selenium.WebElement are in unnamed module of loader 'app')
    at practice.ShadowDomExample.main(ShadowDomExample.java:25)

CODE
package practice;

import java.util.concurrent.TimeUnit;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;

public class ShadowDomExample {

    @SuppressWarnings("deprecation")
    public static void main(String[] args) throws InterruptedException {
        WebDriver driver = new ChromeDriver();
        driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);

        driver.get("https://books-pwakit.appspot.com/");
        driver.manage().window().maximize();

        WebElement root_ShadowHost = driver.findElement(By.cssSelector("book-app[apptitle='BOOKS']"));


        JavascriptExecutor js = (JavascriptExecutor) driver;
        WebElement shadowDOM = (WebElement) js.executeScript("return arguments[0].shadowRoot", root_ShadowHost);


        WebElement appheader = shadowDOM.findElement(By.tagName("app-header"));


        WebElement apptoolbar = appheader.findElement(By.cssSelector("app-toolbar.toolbar-bottom"));


        WebElement bookinputdecorator = apptoolbar.findElement(By.tagName("book-input-decorator"));

        WebElement searchBox = (WebElement) js.executeScript("return arguments[0].querySelector(\"input[aria-label='Search Books']\")", bookinputdecorator);

        searchBox.sendKeys("Testing");

        System.out.println("Succesfully typed into the search box ");

        driver.quit();
    }
}

Solution

  • Shadow root can't be casted to WebElement, it is actually not WebElement, it's other instance, which js props are different. To make your code work, you should get first shadow DOM child and cast it to WebElement

    driver.get("https://books-pwakit.appspot.com/");
    driver.manage().window().maximize();
    
    WebElement shadowHost = driver.findElement(By.cssSelector("book-app[apptitle='BOOKS']"));
    JavascriptExecutor js = (JavascriptExecutor) driver;
    WebElement appHeader = (WebElement) js.executeScript("return arguments[0].shadowRoot.querySelector('app-header')", shadowHost);
    WebElement bookInputDecorator = appHeader.findElement(By.tagName("book-input-decorator"));
    WebElement searchBox = (WebElement) js.executeScript("return arguments[0].querySelector(\"input[aria-label='Search Books']\")", bookInputDecorator);
    searchBox.sendKeys("Testing");