使用量角器切换到 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 后找不到使用定位器错误的元素的主要内容,如果未能解决你的问题,请参考以下文章
量角器+故事书:失败:使用定位器找不到元素:By(css选择器)