Why can't I click on button within a embed element using Selenium C#?

26 Views Asked by At

There is an embed element within an iframe element in the page. It contains a pdf viewer and I want to click on the download arrow.

enter image description here

<div id="__pdfviewer0" data-sap-ui="__pdfviewer0" role="document" aria-label="PDF-Viewer" style="width: 100%; height: 100%;">
    <iframe id="__pdfviewer0-iframe" src="blob:https://foo#view=FitH" aria-label="PDF-Viewer: Inhalt" class="sapMPDFViewerContent" cd_frame_id_="fooCodeframe"/>
    #document (blob:https://foo#view=FitH)
        <!DOCTYPE html>
        <html>
            <head><head/>
            <body style="height: 100%; width: 100%; overflow: hidden; margin:0px; background-color: rgb(82, 86, 89);">
                <embed name="fooCode" style="position:absolute; left: 0; top: 0;" width="100%" height="100%" src="about:blank" type="application/pdf" internalid="fooCode"/>
            </body>
        </html>
   </iframe>
</div>

The code within the iframe looks like this:

iframe code

I think that a valid CSSelector for the cr-icon-button would be:

[id=viewer] /deep/ [id=toolbar] /deep/ [id=end] > [id=downloads] /deep/ [id='download']

So I tried this:

var frame = Client.Value.WebDriver.SwitchTo().Frame(FindElement(By.Id("__pdfviewer0-iframe")));
frame.FindElement(By.CssSelector("[id=viewer] /deep/ [id=toolbar] /deep/ [id=end] > [id=downloads] /deep/ [id='download']")).Click();

But it doesn't work. It can't find the button.

1

There are 1 best solutions below

0
JeffC On

The problem is that the element you want is nested in four shadow-roots. They are similar to IFRAMEs in that you need to switch context into them for Selenium to be able to see the DOM inside. In this case, you'll need to switch into the IFRAME and then switch into the nested shadow-roots. Something like the below should work.

WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
wait.Until(ExpectedConditions.FrameToBeAvailableAndSwitchToIt(By.Id("__pdfviewer0-iframe")));

IWebElement shadowHost1 = driver.FindElement(By.Id("viewer"));
ISearchContext shadowRoot1 = shadowHost1.GetShadowRoot();
IWebElement shadowHost2 = shadowRoot1.FindElement(By.Id("toolbar"));
ISearchContext shadowRoot2 = shadowHost2.GetShadowRoot();
IWebElement shadowHost3 = driver.FindElement(By.Id("downloads"));
ISearchContext shadowRoot3 = shadowHost3.GetShadowRoot();
IWebElement shadowHost4 = driver.FindElement(By.Id("download"));
ISearchContext shadowRoot4 = shadowHost3.GetShadowRoot();
shadowRoot4.FindElement(By.Id("icon")).Click();

For more info on accessing shadow-roots, see this article.