org.openqa.selenium.NoSuchElementException:尝试通过CssSelector定位card-fields-iframe时,返回的节点(空)不是DOM元素

org.openqa.selenium.NoSuchElementException:尝试通过CssSelector定位card-fields-iframe时,返回的节点(空)不是DOM元素

问题描述:

我正在尝试通过部分ID定位iframe.对于这种方法,我使用了: driver.switchTo().frame(driver.findElement(By.cssSelector("iframe[id*='card-fields-number']")));我也尝试过xpath.

I am trying to locate an iframe by partial id. For this method, I used: driver.switchTo().frame(driver.findElement(By.cssSelector("iframe[id*='card-fields-number']"))); I have also tried xpath.

 driver.switchTo().frame(driver.findElement(By.xpath("//iframe[contains(@id,'card-fields-number')]")));

但是,我仍然收到此异常:

However, I still receive this exception:

org.openqa.selenium.NoSuchElementException: Returned node (null) was not a DOM element

我发现,当我为HtmlUnit启用javascript时,它能够找到框架并切换到该框架.我宁愿不启用javascript,因为它对我来说运行非常缓慢,并增加了不必要的延迟.

I found out that when I enable javascript for HtmlUnit, it is able to locate the frame, and switch to it. I would rather not enable javascript as it runs very slow for me, and adds unneeded delay.

iFrame HTML代码:

iFrame HTML code:

<iframe class="card-fields-iframe" frameborder="0" id="card-fields-number-7pbvqg7azsf00000" name="card-fields-number-7pbvqg7azsf00000" scrolling="no" src="https://checkout.shopifycs.com/number?identifier=438599641d0ed8fe61c161d72e62b5f8&amp;location=https%3A%2F%2Fshopnicekicks.com%2F2192362%2Fcheckouts%2F438599641d0ed8fe61c161d72e62b5f8&amp;dir=ltr&amp;fonts[]=Lato" title="Field container for: Card number" style="height: 43px;"></iframe>

iFrame ID是动态的,因此这就是为什么我使用部分ID的原因.

iFrame ID is dynamic, so that is why I resort to using partial ID.

网站链接: https://shopnicekicks.com/checkout 您必须填写所有内容,直到到达信用卡信息页面的最后一页.

Website link: https://shopnicekicks.com/checkout You must fill everything out until you reach the last page, which is the credit card information page.

更新 iFrame在父框架的内部. 父框架:

Update The iFrame is inside of the parent frame. Parent Frame:

<iframe srcdoc="<script>!function(){var e=function(e){var t={exports:{}};return e.call(t.exports,t,t.exports),t.exports},t=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,&quot;value&quot;in i&amp;&amp;(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&amp;&amp;e(t.prototype,n),i&amp;&amp;e(t,i),t}}(),n=function(e,t){if(!(e instanceof t))throw new TypeError(&quot;Cannot call a class as a function&quot;)},i=function(e){return e&amp;&amp;e.__esModule?e:{&quot;default&quot;:e}},o=e(function(e,i){&quot;use strict&quot;;Object.defineProperty(i,&quot;__esModule&quot;,{value:!0});var o=function(){function e(){var t=this;n(this,e),this.calls=[],window.ga=function(){for(var e=arguments.length,n=Array(e),i=0;i<e;i++)n[i]=arguments[i];return t.gaCall(n)}}return t(e,[{key:&quot;gaCall&quot;,value:function(e){var t=this;this.calls.push(e),clearTimeout(this.timeout),this.timeout=setTimeout(function(){t.calls.length>0&amp;&amp;t.sendMessage()},0)}},{key:&quot;listen&quot;,value:function(){var e=this;window.addEventListener(&quot;message&quot;,function(t){return e.receiveMessage(t)},!1)}},{key:&quot;sendMessage&quot;,value:function(){window.parent.postMessage({type:&quot;analytics&quot;,calls:this.calls},this.origin),this.calls=[]}},{key:&quot;receiveMessage&quot;,value:function(e){if(e.source===window.parent&amp;&amp;&quot;checkout_context&quot;===e.data.type){this.origin=e.origin,window.Shopify=e.data.Shopify,window.__st=e.data.__st;try{window.additionalScripts()}catch(e){console.error(&quot;User script error: &quot;,e)}}}}]),e}();i[&quot;default&quot;]=o});e(function(){&quot;use strict&quot;;var e=i(o);!function(){(new e[&quot;default&quot;]).listen()}()})}(&quot;undefined&quot;!=typeof global?global:&quot;undefined&quot;!=typeof window&amp;&amp;window); window.additionalScripts = function () {};</script>" src="https://checkout.shopify.com/2192362/sandbox/google_analytics_iframe" onload="this.setAttribute('data-loaded', true)" sandbox="allow-scripts" id="google-analytics-sandbox" tabindex="-1" class="visually-hidden" style="display:none" aria-hidden="true" data-loaded="true"></iframe>

此错误消息...

org.openqa.selenium.NoSuchElementException: Returned node (null) was not a DOM element

...表示未找到此类元素,因为返回的节点为或不是DOM元素.

...implies that there was no such element found as the returned node was null or was not a DOM element.

这仍然是带有 htmlunit-driver的公开问题 团队.

This is still a open issue with htmlunit-driver team.

但是,您需要注意以下某些事项:

However there are certain things which you need to take care as follows:

  • 首先,所有现代浏览器都内置了对JavaScript的支持.
  • HtmlUnitDriver WebDriver 兼容的驱动程序,用于 HtmlUnit 无头浏览器.它具有相当好的 JavaScript 支持(正在不断改进),并且即使与非常复杂的AJAX库(模拟 Chrome Firefox Internet Explorer ,具体取决于所使用的配置.因此,理想情况下,在使用 HtmlUnitDriver 时,必须启用 JavaScript ,否则 HtmlUnitDriver 可能无法检测到 JavaScript 基础元素.
    • 您可以在
    • First and foremost, all the modern browsers come with built-in support for JavaScript.
    • HtmlUnitDriver is a WebDriver compatible driver for HtmlUnit headless browser. It has fairly good JavaScript support (which is constantly improving) and is able to work even with quite complex AJAX libraries, simulating Chrome, Firefox or Internet Explorer depending on the configuration used. So ideally while working with HtmlUnitDriver, JavaScript must be enabled, else HtmlUnitDriver may not ne able to detect the JavaScript based elements.
      • You can find a detailed discussion in HtmlUnitDriver does not load javascript when navigating a page from an url

      因此您可以使用以下任一解决方案:

      So you can use either of the following solutions:

      • cssSelector :

      new WebDriverWait(driver, 10).until(ExpectedConditions.frameToBeAvailableAndSwitchToIt(By.cssSelector("iframe.card-fields-iframe[id^='card-fields-number-'][src*='shopifycs']")));
      

    • xpath :

      new WebDriverWait(driver, 10).until(ExpectedConditions.frameToBeAvailableAndSwitchToIt(By.xpath("//iframe[@class='card-fields-iframe' and starts-with(@id,'card-fields-number-')][contains(@src, 'shopifycs')]")));
      

    • 请参见CssSelector的快照,该快照根据您提供的HTML标识了perfecto元素:

      See the snapshot of the CssSelector which identifies the element perfecto as per the HTML you have provided: