【问题标题】:How to SendKeys to input element that is created ad hoc when clicking in div element parent?单击 div 元素父级时,如何将密钥发送到临时创建的输入元素?
【发布时间】:2018-07-31 22:57:59
【问题描述】:

我陷入了这个问题:我们的网页有一个动态表,它将在div 元素上加载值(学生的分数)。如果我们点击上面提到的div,一个新的子元素input将被附加到div,我们应该可以使用SendKeys方法输入一个新的标记。但是,当我尝试发送密钥时,会出现 StaleElementReferenceException

这是添加 input 时的元素(必须使用断点,因为一旦 div 元素失去焦点,元素就会消失):


<tr>
    <td class="indice">1</td>
    <td id="accion-1-alumno-0" data-tooltip="" title="Bustos, Guido" class="has-tip titulo">Bustos, Guido</td>
    <td data-tooltip="" title="1º ESA" class="has-tip titulo">1º ESA</td>
    <td class="nota relative  media noeditable k-nivel2_tabla" style="text-align:center; color: #ed1c24!important">
        <div id="accion-1-celda-0-0-0" class="elemento comentarios">2,00</div>
    </td>
    <td class="nota relative " style="text-align:center; color: #ed1c24!important">
        <div id="accion-1-celda-1-0-0" class="elemento comentarios">
            <input id="editor" type="text" value="2" maxlength="7">
        </div>
    </td>
    <td class="nota relative " style="text-align:center; color: #000000!important">
        <div class="elemento comentarios">
            <span id="accion-1-editar-2-0" class="block left ellipsis span  comentario" title=""></span>
            <span id="accion-1-prismaticos-2-0" class="glyphicons glyph_observaciones observacion right"></span>
        </div>
    </td>
</tr>

这是我用来点击div并尝试SendKeys的代码:


IWebElement inputNota = SeleniumHelper.FindByXPath("//td[text() = '"+ nombreAlumno +"']/following-sibling::td/div[contains(@id, 'accion-1-celda')]");

SeleniumHelper.Click(inputNota);

SeleniumHelper.SendKeys(inputNota.FindElement(By.Id("editor")), nota);

感谢您的宝贵时间

【问题讨论】:

    标签: c# html selenium exception


    【解决方案1】:

    如果将新元素附加到 html,则意味着 DOM 已刷新,或者至少是 &lt;div&gt;,因此 driver“丢失”了先前定位的元素。你需要重新定位它

    string locator = "//td[text() = '"+ nombreAlumno +"']/following-sibling::td/div[contains(@id, 'accion-1-celda')]";
    
    IWebElement inputNota = SeleniumHelper.FindByXPath(locator);
    
    SeleniumHelper.Click(inputNota);
    
    SeleniumHelper.SendKeys(SeleniumHelper.FindByXPath(locator).FindElement(By.Id("editor")), nota);
    

    【讨论】:

    • 嗨@Guy,我更改为第二次搜索定位器,正如您所建议的那样,行为如下:selenium 正确单击元素,但未显示输入弓并且 NoSuchElement 异常显示。我尝试添加一个睡眠只是为了确保输入框会显示,但事实并非如此。
    • @elgato 如果元素被正确点击,输入字段不应该出现吗? nombreAlumno 变量的值是多少?也许点击不起作用(即使您没有收到任何错误)。
    • 点击发生是因为点击元素时框上有一个红点,所以我确信点击是正确的。我也很困惑为什么盒子没有出现。 nombreAlumno 的值为 "Bustos, Guido"
    • @elgato 澄清一下,您是在尝试单击 ID 为 accion-1-celda-0-0-0 还是 ID 为 accion-1-celda-1-0-0 的元素?
    • 这就是问题所在。我的 xpath 是: string xpathNota = "//td[text() = '" + nombreAlumno + "']/following-sibling::td/div[contains(@id, 'accion-1-celda')]";将其更改为: string xpathNota = "//td[text() = '" + nombreAlumno + "']/following-sibling::td/div[contains(@id, 'accion-1-celda-1')] ";成功了。谢谢!
    【解决方案2】:

    当元素从 DOM 中删除/更改时会发生 StaleElement。在任何情况下,您都需要重新抓取该元素。一个很好的方法就是这样......

    public static IWebElement HardFindElement(IWebDriver driver, By by)
        {
            IWebElement elementToReturn = null;
    
            WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(30));
            wait.Until(drv =>
            {
                try
                {
                    elementToReturn = driver.FindElement(by);
                    return true;
                }
                catch
                {
    
                    return false;
                }
            });
    
            return elementToReturn;
        }
    

    这将等待最多 30 秒,直到它能够从 DOM 中重新获取元素。您需要在单击后执行此操作以相应地重新初始化元素

    【讨论】:

    • 好吧,现在你在某个地方学习并写下了这个答案,嗯?这真的很棒。所以不要太着急说某人幼稚或类似的东西。我真的想帮你。我想告诉你,从 DOM 中删除的元素并不完全是陈旧元素,当对元素的引用丢失时,它就会变成陈旧元素。
    • @Rajagopalan 我最初的答案仍然是正确的,但在使用基于页面对象模式的框架的意义上,我相信这不是。因此,我定制了一个使用 FindsBy 属性的解决方案(因为这个问题不包括使用 PageFactory)。在任何情况下,当一个元素从 DOM 中移除时,引用也是如此。如果使用页面对象模式,硒仍然可以通过多种方式重新获得该引用。在这种情况下,重新获取元素会更容易,而不是重新构建整个框架以使用页面对象模式。
    • 你已经明确表示他必须等到元素变得可见的答案,不仅是你的答案,你的代码完美地完成了这项工作。所以对我来说很明显你误会了陈旧的元素。但如果你不准备承认也没关系!让我们继续!再一次,您的理解有误,当元素过时时,不需要从 DOM 中删除元素。你的理解还是错的。
    • @Rajagopalan 我知道元素需要在 DOM 中简单地更改才能过时,而不是被删除。但是要在 Angular 应用程序中的 DOM 中进行更改,它通常会被删除并相应地重新添加到 DOM 中(使用新数据重新缓存)。我意识到没有指定这是否是我假设的角度应用程序。我承认这是我产生误解的原因。
    • 嗨@Taran,驱动程序已经包含在一个考虑到等待元素出现的帮助器中,并且确实我使用的是 POM 结构,所以问题不完全是,但谢谢你你的时间
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-11
    • 1970-01-01
    • 1970-01-01
    • 2010-11-02
    • 1970-01-01
    • 2015-10-05
    相关资源
    最近更新 更多