【问题标题】:Selenium StaleElementException after refilling in form after submission提交后重新填写表单后的 Selenium StaleElementException
【发布时间】:2017-07-19 16:54:06
【问题描述】:

我有一个表单,我正在尝试自动填写我的一个 Selenium 脚本。有一个表单有大约 4 个文本字段,其中的 HTML 看起来像这样

<input class="class" id="id" name="name" value="" autocomplete="off" wtx-context="stuff" type="text">

然后在填写完这些表单后,会有一个输入提交按钮,其 HTML 代码如下

<input id="id2" class="class2" value="Add Material" wtx-context="morestuff" type="submit">

我已经使用了以下 Java 代码,并且成功地让表单被填写和提交,但是一旦提交,我认为发生的事情是它们在 DOM 上被刷新,然后我得到一个 StaleElement 异常抛出对我。我通过转到主页并使用表单导航回到网页来绕过它,但是如果有人知道,我正在寻找一种更优雅的解决方案。下面是我的 Java 代码。

Page.WriteToField(Page.Input_number(), "111111111");
Page.WriteToField(Page.Input_number2(), "222222222");
Page.WriteToField(Page.Input_date(), format.format(cal.getTime()));
Page.WriteToField(Page.Input_number3(), "3333");
Page.SubmitIngredient();

WriteToField() 函数看起来像这样

public void WriteToField(WebElement field, String text) {
    field.click();
    field.clear();
    field.sendKeys(text);
}

我使用以下格式从我的页面类中访问所有 WebElements

public WebElement Input_number() {
        return wait.until(ExpectedConditions.elementToBeClickable(By.id("form1")));
}

【问题讨论】:

  • 你什么时候真正得到你的StaleElement异常? Input_Number 是如何构造的?如果页面正在重新加载,如果您使用 PO 模型,您可能希望 SubmitIngredient() 返回一个新的 PageObject。如果没有,看起来您在提交表单后仍想重新创建该对象,因为页面正在重新加载(可能)。
  • 您可能需要在Page.SubmitIngredient(); 之后添加某种等待,以确保页面已完成(重新)加载,然后才能继续执行脚本。
  • @mrfreester 一旦我在提交后尝试将新输入写入表单,就会出现 StaleElement 异常。返回一个新的 PageObject 是什么意思?
  • @Qyler 本质上它已经过时了,因为页面重新加载,所以你必须重新找到所有元素。因此,在您提交后,您需要重建您的对象。因此,如果您 return new WhateverPage() 为您的 SubmitIngredient() 方法,您可以执行 WhateverPage whateverPage = Page.SubmitIngredient(); whateverPage.WriteToField(blahblah); 这将有效,因为您正在创建一个新实例,为下一轮查找所有字段。
  • @Qyler 我想我可以提供一个答案,但我必须看看Page 是如何被初始化的,并且可能是第一次成功编写,然后第二次尝试失败的完整示例看看这两次尝试之间的代码流。你有机会提供你的代码吗?

标签: javascript java ajax forms selenium


【解决方案1】:

在实际检查元素是否可点击之前,您为什么不尝试检查它是否存在?

public WebElement Input_number() {
      wait.until(ExpectedConditions.presenceOfElementLocated(By.id("form1")));
      return wait.until(ExpectedConditions.elementToBeClickable(By.id("form1")));
}

更新- 我要求为元素的存在添加预期条件的原因是它确实再次执行查找元素操作。 [请参考下面presenceOfElementLocated 方法的实现] 所以我希望能得到元素作为回报。 [但我可能错了]

public static ExpectedCondition<WebElement> presenceOfElementLocated(final By locator) {
    return new ExpectedCondition<WebElement>() {
        public WebElement apply(WebDriver driver) {
            return ExpectedConditions.findElement(locator, driver);
        }

        public String toString() {
            return "presence of element located by: " + locator;
        }
    };
}

除此之外,如果您检查elementToBeClickable 方法的实现[下面的代码块],它不会执行查找操作,并且如果元素不可见或启用它会引发StaleElementReferenceException 异常。

 public static ExpectedCondition<WebElement> elementToBeClickable(final WebElement element) {
    return new ExpectedCondition<WebElement>() {
        public WebElement apply(WebDriver driver) {
            WebElement visibleElement = (WebElement)ExpectedConditions.visibilityOf(element).apply(driver);

            try {
                return visibleElement != null && visibleElement.isEnabled()?visibleElement:null;
            } catch (StaleElementReferenceException var4) {
                return null;
            }
        }

        public String toString() {
            return "element to be clickable: " + element;
        }
    };
}

所以在检查元素是否可见之前检查元素的存在对我来说是有意义的[正如我之前所说,我可能错了]

【讨论】:

  • 如果不存在则无法点击。不需要第一次等待。
猜你喜欢
  • 1970-01-01
  • 2017-11-07
  • 2018-04-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-22
  • 1970-01-01
相关资源
最近更新 更多