C# Selenium-发送密钥以在影子根(open)和多个iFrame中输入挪威银行ID的密码

C# Selenium-发送密钥以在影子根(open)和多个iFrame中输入挪威银行ID的密码,c#,selenium,iframe,shadow-dom,webdriverwait,C#,Selenium,Iframe,Shadow Dom,Webdriverwait,我想使用来自挪威银行ID的测试数据进行自动测试。但我无法使用Selenium获得输入字段 我想做的是: 去 点击“洛格酒店” 点击“BankID påmobil” 单击“用于登录的替代程序”下的“银行ID” 输入“02105892090”(来自上面链接的测试用户)并单击“Logg inn” 在“Engangskode”中再次输入“02105892090”,然后单击提交按钮 HTML: 但我得到了错误信息: OpenQA.Selenium.NoSuchElementException : no s

我想使用来自挪威银行ID的测试数据进行自动测试。但我无法使用Selenium获得输入字段

我想做的是:

  • 点击“洛格酒店”
  • 点击“BankID påmobil”
  • 单击“用于登录的替代程序”下的“银行ID”
  • 输入“02105892090”(来自上面链接的测试用户)并单击“Logg inn”
  • 在“Engangskode”中再次输入“02105892090”,然后单击提交按钮
  • HTML:

    但我得到了错误信息:

    OpenQA.Selenium.NoSuchElementException : no such element: Unable to locate element: {"method":"css selector","selector":"input[type='password']"}
    
    有人知道怎么做吗

    编辑:

    在大家的帮助下,这是最终起作用的代码:

    public void EnterSsn(string ssn)
    {
        var driver = WebDriverFacade.GetDriver;
        driver.SwitchTo().DefaultContent();
    
        new WebDriverWait(driver, TimeSpan.FromSeconds(20)).Until(ExpectedConditions.FrameToBeAvailableAndSwitchToIt(By.CssSelector("iframe#ifmSingicat")));
        new WebDriverWait(driver, TimeSpan.FromSeconds(20)).Until(ExpectedConditions.FrameToBeAvailableAndSwitchToIt(By.CssSelector("#bankid-container iframe")));
        new WebDriverWait(driver, TimeSpan.FromSeconds(20)).Until(ExpectedConditions.ElementToBeClickable((IWebElement)((IJavaScriptExecutor)driver).ExecuteScript("return document.querySelector(\".full_width_height\").shadowRoot.querySelector(\"input[type=\'password\']\")"))).SendKeys(ssn);
    }
    
    这里有2个iframe(嵌套iframe),因此需要切换两次。 首先切换到id为ifmSingicat的iframe,然后切换到切换的iframe的第一个iframe

    //Main document
    driver.SwitchTo().DefaultContent();
    
    //Find the first frame, and use switch to frame
    IWebElement containerFrame = driver.FindElement(By.Id("ifmSingicat"));
    driver.SwitchTo().Frame(containerFrame);
    
    //You are now in iframe "containerFrame", now find the nested iframe
    IWebElement contentFrame = driver.FindElement(By.CssSelector("#bankid-container iframe"));
    driver.SwitchTo().Frame(contentFrame);
    
    //Now find the elements you want in the nested frame
    IWebElement foo = driver.FindElement(By.CssSelector("input[type='password']"));
    

    注意:我不是C#开发者,希望上面的语法是正确的。

    如果切换到正确的iframe,那么只需要添加一些等待。它将提供一些时间来加载iframe元素。

    与文本Engangskode关联的字段位于父
    中的子
    中的\shadow root(open)中。因此,要将字符序列发送到所需字段,您需要:

    • 诱导WebDriverWait使父帧可用并切换到它
    • 诱导WebDriverWait使子帧可用并切换到它
    • 为所需的
      元素导入WebDriverWait to Eclickable()
      ,该元素位于
      #shadow root(open)

    • 您可以使用以下解决方案:

      new WebDriverWait(driver, TimeSpan.FromSeconds(20)).Until(ExpectedConditions.FrameToBeAvailableAndSwitchToIt(By.CssSelector("iframe#ifmSingicat")));
      new WebDriverWait(driver, TimeSpan.FromSeconds(20)).Until(ExpectedConditions.FrameToBeAvailableAndSwitchToIt(By.CssSelector("iframe[title='BankID']")));
      new WebDriverWait(driver, TimeSpan.FromSeconds(20)).Until(ExpectedConditions.ElementToBeClickable((IWebElement)((IJavaScriptExecutor)driver).ExecuteScript("return document.querySelector('div.full_width_height').shadowRoot.querySelector('input')"))).SendKeys("02105892090");
      
    • 浏览器快照:


    你切换到iframe了吗?@NaelAbdeljawad我添加了一些代码来解释我所做的事情@NaelAbdeljawad谢谢你的回复。运行代码时,我被卡在上一页。我得到一个错误:“OpenQA.Selenium.NoSuchElementException:没有这样的元素:无法定位元素:{“方法”:“css选择器”,“选择器”:“#ifmSingicat”}”是的,我可以,但只要我尝试切换到iframe,我就会收到错误消息。我想它还没有加载?您可以在第一次切换时调试并添加断点,或者添加线程睡眠几秒钟来发现问题。我建议在运行脚本时观察浏览器行为。非常感谢@DebanjanB!经过一些修改,它终于成功了。将我的解决方案添加到原始帖子中。
    //Main document
    driver.SwitchTo().DefaultContent();
    
    //Find the first frame, and use switch to frame
    IWebElement containerFrame = driver.FindElement(By.Id("ifmSingicat"));
    driver.SwitchTo().Frame(containerFrame);
    
    //You are now in iframe "containerFrame", now find the nested iframe
    IWebElement contentFrame = driver.FindElement(By.CssSelector("#bankid-container iframe"));
    driver.SwitchTo().Frame(contentFrame);
    
    //Now find the elements you want in the nested frame
    IWebElement foo = driver.FindElement(By.CssSelector("input[type='password']"));
    
    new WebDriverWait(driver, TimeSpan.FromSeconds(20)).Until(ExpectedConditions.FrameToBeAvailableAndSwitchToIt(By.CssSelector("iframe#ifmSingicat")));
    new WebDriverWait(driver, TimeSpan.FromSeconds(20)).Until(ExpectedConditions.FrameToBeAvailableAndSwitchToIt(By.CssSelector("iframe[title='BankID']")));
    new WebDriverWait(driver, TimeSpan.FromSeconds(20)).Until(ExpectedConditions.ElementToBeClickable((IWebElement)((IJavaScriptExecutor)driver).ExecuteScript("return document.querySelector('div.full_width_height').shadowRoot.querySelector('input')"))).SendKeys("02105892090");