使用量角器切换到 iframe 后找不到使用定位器错误的元素

Posted

技术标签:

【中文标题】使用量角器切换到 iframe 后找不到使用定位器错误的元素【英文标题】:No element found using locator error after switching to iframe using protractor 【发布时间】:2021-03-02 03:51:56 【问题描述】:

我一直在尝试使用 protractor selenium 从网页下载嵌入式 PDF。我目前不得不实际下载文件,因为我总是收到以下错误:

失败:使用定位器找不到元素:By(css selector, *[id="download"])

切换到框架后也找不到按钮。

我也尝试了答案here 中指出的方法,它提取 src 属性值并直接转到 URL,但同样的问题。找不到下载按钮(图标)。

我们有相同的确切要求,我们只需要单击嵌入在 PDF 中的下载图标,该图标恰好位于 iframe 中。示例页面如this。

这是我的代码 sn-p。

        const iframe = $('#printFrame'),            
              downloadBtn = $('#download'),
              content = $('#content');

        await this.disableWaitForAngular();
        await browser.wait(EC.visibilityOf(iframe),waitTimeout);
        console.log("Switching to iframe...");
        await browser.switchTo().frame(iframe.getWebElement());

        await browser.wait(EC.visibilityOf(content), waitTimeout);
        await browser.actions().mouseMove(content).perform();

        console.log("Waiting for download button.");
        await browser.wait(EC.visibilityOf(downloadBtn), waitTimeout);

        await downloadBtn.click();

        await browser.switchTo().defaultContent();
        await this.enableWaitForAngular();

更新:

尝试在切换帧之前和之后按照建议的答案之一的建议注入以下代码,但它给了我一个错误。

const downloadIcon: WebElement = await browser.executeScript('return document.querySelector("#viewer").shadowRoot.querySelector("#toolbar").shadowRoot.querySelector("#downloads").shadowRoot.querySelector("#download").shadowRoot.querySelector("#icon > iron-icon");');

    await downloadIcon.click();

错误:

 - Failed: javascript error: Cannot read property 'shadowRoot' of null
(Session info: chrome=87.0.4280.66)
(Driver info: chromedriver=87.0.4280.20 (c99e81631faa0b2a448e658c0dbd8311fb04ddbd-refs/branch-heads/4280@#355),platform=Windows NT 10.0.14393 x86_64)

下载图标供参考:

【问题讨论】:

不确定它是否会有所帮助,但请尝试获取 frem,例如:browser.switchTo().frame(1) 我实际上已经尝试过了,并且出现了错误。找不到框架。 要使用 Chrome 下载嵌入的 PDF,请使用偏好设置 'plugins.always_open_pdf_externally": true 启动浏览器,切换到框架 iframe[src$=pdf] 并单击 #open-button 【参考方案1】:

在您提供的example page 上,没有“下载”按钮,因为该按钮是浏览器的一部分,而不是页面。使用任何类型的选择器都找不到它。

但我们将pdf 加载为iframe,因此我们可以创建自己的下载按钮:

a = document.createElement('a'); a.href = $('iframe').src; a.download = "hello.pdf"; a.click();

所以复制这段代码,转到your page,将其粘贴到控制台并运行。这将下载文件。

这只是一个例子,但也许你可以根据自己的需要调整这个想法。

更新

好的,我将尝试解释引擎盖下的内容。以下是不同浏览器中的相同page:Chrome、FF、Edge、IE。

如您所见,PDF页面的“内容”是不同的,因为它不是页面相关的,它是由浏览器和它的插件控制的。

按“下载”图标/按钮与按插件内的某些内容相同。这是不可能的。

其实页面本身里面只有PDF对象,没有控件。

例如在 IE 中你找不到“下载”按钮。它根本不存在,但我们可以按它(“在浏览器中”,而不是“在页面中”),看:

【讨论】:

下载按钮将在鼠标悬停时可见。请参阅图片说明。它实际上是一个下载图标,而不是“下载”按钮。谢谢! @Harvey 好的,我在答案中添加了描述和图像。请看一看。 我现在明白你的意思了。非常感谢您的解释。我很感激。我已经尝试将您提供的 js 代码粘贴到控制台,它确实有效。将尝试使用打字稿模仿这一点。谢谢【参考方案2】:

我认为您遇到的问题是由于 shadow-root。

    尝试使用by.deepCss(selector) Protractor 方法。如果这不起作用,请查看解决方法here。

    您可以获取 iframe 的src 属性并在新窗口中打开它。然后sendKeys Ctrl+S。

    您可以尝试在量角器中作为 JavaScript 代码运行:

    document.querySelector("#viewer").shadowRoot.querySelector("#toolbar").shadowRoot.querySelector("#downloads").shadowRoot.querySelector("#download").shadowRoot.querySelector("#icon > iron-icon").click();

我在检查元素并从 Chrome DevTools 中选择“复制 JS 路径”时得到了这个。

参考:How to interact with the elements within #shadow-root (open) while Clearing Browsing Data of Chrome Browser using cssSelectordeepCss is failing to identify an element inside the shadow root in ProtractorProtractor: Unable select input element inside a shadow DOM (Polymer) using by.deepCss('input')https://www.protractortest.org/#/api?view=ProtractorBy.prototype.deepCsshttps://superuser.com/questions/505899/keyboard-shortcuts-for-chrome-pdf-viewer

【讨论】:

第一次遇到这个词。所以我真的认为这会解决我的问题。我已经尝试在我的代码中注入您所建议的内容,即 JS 路径的值。但是后来我遇到了这个错误。失败:javascript 错误:无法读取 null 的属性“shadowRoot”。还尝试先切换到 iframe,但没有成功。 你可以试试deepCss量角器法protractortest.org/#/api?view=ProtractorBy.prototype.deepCss。 我尝试了另一个看起来很有希望的 appoarch - 在新窗口中打开 iframe 中的源代码w3docs.com/uploads/media/default/0001/01/… 然后 sendKeys Ctrl+S 以下载它。我会将我的两个建议添加到我的答案中。 尝试了您的第二个建议,该建议更容易实施。但是我不确定要发送什么元素,所以我尝试使用正文发送。等待元素(by.css('body')).sendKeys(Key.chord(Key.CONTROL, 's'));没有运气。所以将尝试第一个建议,使用 shadowroot 解决方法。非常感谢。感谢帮助。会更新你。 我也尝试了非元素变体:browser.actions().keyDown(Key.CONTROL).sendKeys('s').keyUp(Key.CONTROL).perform();跨度> 【参考方案3】:

在量角器中它的反模式将链接和等待混合在一起:

isPDFDownloadSuccessful: () => Promise<boolean> = async() =>         
        await this.disableWaitForAngular(); //function equivalent to browser.waitForAngularEnabled(false);
        const iframe = await element(by.tagName("iframe"));
        console.log("Switching to iFrame...");        
        await browser.switchTo().frame(element(by.tagName('iframe')).getWebElement());
        await element(by.id("download")).click()
     
        //Insert here actions to check successful download 
        return true;    
    ;

【讨论】:

明白。我习惯这样做。我刚刚尝试链接,因为我认为这导致了我的情况不存在的问题。顺便说一句,谢谢!【参考方案4】:

这段代码完成了工作

await browser.waitForAngularEnabled(false);
await browser.get('https://www.sebi.gov.in/enforcement/orders/jun-2019/adjudication-order-in-respect-of-three-entities-in-the-matter-of-prism-medico-and-pharmacy-ltd-_43323.html');
let $iFrame = $('iframe[src*="sebi"]'),
    $downloadButton = $('#download');
await browser.wait(ExpectedConditions.presenceOf($iFrame), 5000);
await browser.switchTo().frame($iFrame.getWebElement());
await browser.wait(ExpectedConditions.presenceOf($downloadButton), 2000);
await $downloadButton.click();
await browser.sleep(2500);
await browser.switchTo().defaultContent();
await browser.waitForAngularEnabled(true);

如果它不起作用,那么您的配置可能有问题,因此您需要更新您的问题并包含其内容

【讨论】:

可能你只需要等待内容加载 好的将尝试增加一些等待。谢谢! 显然,在检查我给的样本不是最接近的。这是我正在使用的最接近的示例页面。 africau.edu/images/default/sample.pdf我已经尝试了几乎与您在我的问题中看到的更新完全相同的代码。 我添加了一个 mouseMove 动作来模拟悬停动作,以使下载图标可见。但仍然没有运气。 1.我已经花时间解决了问题中给出的任务。对于另一个问题,请打开另一个问题。 2.你添加的url只是打开pdf,它与iframe和你描述的问题有什么关系?

以上是关于使用量角器切换到 iframe 后找不到使用定位器错误的元素的主要内容,如果未能解决你的问题,请参考以下文章

切换到 Typescript 后找不到 App.js

量角器+故事书:失败:使用定位器找不到元素:By(css选择器)

selenium之 定位以及切换frame(iframe)

selenium之 定位以及切换frame(iframe)

Selenium2selenium之 定位以及切换frame(iframe)

Selenium基本使用表单切换