关注后的action.SendKeys上的Selenium.StaleElementReferenceException?

时间:2018-01-30 15:50:19

标签: selenium selenium-webdriver

我在使用selenium时遇到了一些问题,特别是使用了操作,尽管这可能只是一个更大问题的症状。要快速解释尝试做什么:

  1. 使用SendKeys(Keys.ArrowDown)向下滚动到页面底部
  2. 我按下按钮,然后将页面更改为其他语言。
  3. 我尝试使用SendKeys(Keys.ArrowDown)向下滚动新页面。这是我收到错误的地方!
  4. 这里奇怪的是,即使我使用相同的功能,我在步骤1中滚动也没有问题,但在步骤3中我收到错误消息:

    OpenQA.Selenium.StaleElementReferenceException:'元素引用是陈旧的;元素不再附加到DOM,它不在当前帧上下文中,或者文档已刷新'

    我试图重新声明我的页脚变量,并将其作为Footer类变量包含(原来它不是),但我没有改变任何东西

    我使用SendKeys而不是MoveToElement的原因是因为MoveToElement不适用于Firefox中的屏幕外元素。我在下面列出了所有相关代码,包括错误的图像以及何时发生。

    有人可以建议我做错了吗?

        [TestMethod]
        public void Reset_newsletter_subscription_form_BR_site()
        {
            Browser.Goto(siteUrl);
            Webpage.Footer.GoTo_CountryPageViaFooter("br");
            Webpage.Footer.ScrollToFooter(); // -> This is where it fails!
            Other.Irrelevant.Stuff();
        }
    

    下面是Selenium部分:

    public static class Browser
    {
        public static IWebDriver webDriver;
        public static Actions actions;
    
        public static void Goto(string url)
        {
            webDriver.Url = url;
        }
    }
    
    public static class Webpage
    {
        public static Footer Footer
        {
            get
            {
                var footer = new Footer(Browser.webDriver, Browser.actions);
                return footer;
            }
         }
     }
    
    public class Footer
    {
        private IWebDriver webDriver;
        private Actions actions;
        private IWebElement footer;
    
        public Footer(IWebDriver webDriver, Actions actions)
        {
            this.webDriver = webDriver;
            this.actions = actions;
        }
        public void GoTo_CountryPageViaFooter(string CountryTag)
        {
    
            footer = webDriver.FindElement(By.ClassName("c-footer"));
            var changeCountryButton = footer.FindElement(By.ClassName("c-footer__toggle-country-selector"));
    
            ScrollToFooter();
    
            actions.MoveToElement(footer).Perform();
            actions.MoveToElement(changeCountryButton).Perform();
            changeCountryButton.Click();
    
            var intPageLink = footer.FindElement(By.XPath("//*[@href='/" + CountryTag + "/']"));
            intPageLink.Click();
        }
    
        public void ScrollToFooter()
        {
    
            footer = webDriver.FindElement(By.ClassName("c-footer"));
    
            //MoveToElement does not work for Firefox, so a workaround is needed.
            if (webDriver is FirefoxDriver)
            {
                int i = 0;
                while (i < 5)
                {
                    actions.SendKeys(Keys.ArrowDown).Perform(); //This is where it fails!
                    i++;
                }
            }
    
            actions.MoveToElement(footer).Perform();
        }
    

    Image of the exception

3 个答案:

答案 0 :(得分:1)

我不会使用.SendKeys()滚动页面。它不会一致。想象一下,如果页面更长或更短......你需要滚动多少次?我认为更好的方法是使用JS将页面滚动到所需的元素。

public void ScrollToFooter()
{
    footer = webDriver.FindElement(By.ClassName("c-footer"));

    // MoveToElement does not work for Firefox, so a workaround is needed
    if (webDriver is FirefoxDriver)
    {
        IJavaScriptExecutor jse = (IJavaScriptExecutor)webDriver;
        jse.ExecuteScript("arguments[0].scrollIntoView();", footer);
    }
    else
    {
        actions.MoveToElement(footer).Perform();
    }
}

如果您决定坚持使用您的方法,那么由于缺少else,您就会遇到错误。如果驱动程序是FF,则在执行滚动代码后,它将执行.MoveToElement()并失败。

您可以简化此功能,只为所有驱动程序使用JS。

public void ScrollToFooter()
{
    footer = webDriver.FindElement(By.ClassName("c-footer"));
    IJavaScriptExecutor jse = (IJavaScriptExecutor)webDriver;
    jse.ExecuteScript("arguments[0].scrollIntoView();", footer);
}

答案 1 :(得分:0)

而不是

actions.SendKeys(Keys.ArrowDown).Perform();

我建议:

webDriver.FindElement(By.cssSelector("body")).sendKeys(Keys.ArrowDown);

答案 2 :(得分:0)

每当调用Perform()方法时,它都会计算如何与Page进行交互。因此,它的工作是找出页面中存在的活动元素(如果未在MoveToElement(元素)中指定元素或在使用Actions单击元素期间)。

所以在你的情况下,因为没有指定Element actions.SendKeys(Keys.ArrowDown).Perform();所以Actions会关注页面中存在的任何活动元素并对其执行SendKeys操作。

Details about Actions Interaction with Web Page..

因此,一旦单击语言更改链接,附加到DOM的元素就会发生变化,因此Selenium Webdriver会将此检测为当前活动元素的更改 StaleElementReference异常抛出。

为了摆脱异常,您可以在两者之间添加等待语句,或者有一种很好的方式handle StaleElementReference Exception given here

谢谢:)