【问题标题】:How to find a dynamic element and send text through Selenium and C#如何通过 Selenium 和 C# 查找动态元素并发送文本
【发布时间】:2019-05-08 01:09:00
【问题描述】:

编辑:不确定它是否真的有助于解决这个问题,但这是基于 Sharepoint 的。

我有一个 Webdriver 找不到的带有特殊字符的元素。

var element = wait.Until(x => x.FindElement(By.Id("Tasrit_6aecdca9-e3b9-4141-ae36-d537784f9592_$TextField_inplacerte")));
element.SendKeys("foo");

我猜是$ 导致了问题。

相反,我是通过使用找到的:

var element = wait.Until(x => x.FindElements(By.CssSelector("div[id*='Tasrit_6aecdca9-e3b9-4141-ae36-d537784f9592']")));
element[2].FindElement(By.TagName("p")).SendKeys("foo");

测试以这种方式通过(看似),但值并没有真正发送到现场。 不幸的是,元素的层次结构中没有input 标记,当手动插入文本时,我可以看到该值已插入到<p> 标记中。但是,如图所示,当使用 <p> 标签时,它并没有真正的帮助。

HTML:

<div class="ms-rtestate-write ms-rteflags-0 ms-rtestate-field" id="Tasrit_6aecdca9-e3b9-4141-ae36-d537784f9592_$TextField_inplacerte" role="textbox" aria-haspopup="true" aria-labelledby="Tasrit_6aecdca9-e3b9-4141-ae36-d537784f9592_$TextField_inplacerte_label" style="min-height: 84px;" contenteditable="true" aria-autocomplete="both" aria-multiline="true" RteDirty="true">
  <p>
    <span id="ms-rterangecursor-start" RteNodeId="1"></span>
    <span id="ms-rterangecursor-end"></span>
  ​</p>
</div>

【问题讨论】:

  • 使用基于文本的相关 HTML 更新问题
  • 检查多余的空间,见下文。
  • 这个 ID 似乎是动态的。你有 3 个这样的 ID?
  • 是的。我应该感谢 Microsoft Dynamics CRM :) ..但在这种情况下,它只是看起来是动态的,它不是。每次我跑步时它都保持不变。无论如何,当我使用 id* (contains) 时也会发生这种情况
  • 如果您将文本发送给父 &lt;div&gt; 会发生什么?

标签: c# selenium selenium-webdriver xpath css-selectors


【解决方案1】:

我猜该元素的 id 中有多余的空间 :) 试试这个:

wait.Until(x => x.FindElement(By.Id("Tasrit_6aecdca9-e3b9-4141-ae36-d537784f9592_$TextField_inplacerte")));
element.Click();

或者 DOM 中该元素的 Id 值不同$TextField_inplacerte 是解析为例如的变量。 spaceMonkey, undefined, 5 etc. 打开开发工具,找到元素,右键单击,检查并确认 DOM 中元素的实际 Id。

您可以使用开发工具 API 在当前打开的页面(其中包含该元素)的 DOM 中搜索文本,如果它与 Id 匹配,如果不存在差异。它可以是任何部分,例如。 Id 中的第 6 个字符不同:)

只是为了确保您提到的 id 的第一部分和 24 之间的空间是您可以解决的问题:

  1. 查看 webdriver 的代码,并在内部查看用于访问 DOM 元素的内容

  2. 在测试之前加载 jquery:

    var element = wait.Until(x => x.FindElements($('#id 包含 空格')).SendKeys("foo");

基本上,不是使用 webdriver 方式查找元素,而是使用 jQuery 获取元素引用。如果这样可行,那就是空间问题,因为应用程序的设计不佳,在元素的 id 中有空间

这可能就是 CSS 选择器路由起作用的原因。

【讨论】:

  • 使用开发工具 API 时,id 现在是 #Tasrit_6aecdca9-e3b9-4141-ae36-d537784f9592_\24 TextField_inplacerte
  • 所以完全输入,而不是你输入的内容。wait.Until(x => x.FindElement(By.Id("Tasrit_6aecdca9-e3b9-4141-ae36-d537784f9592_\24 TextField_inplacerte") ));如果它总是一样的话。
  • 您注意到24TextField 之间有一个空格吗?我应该完全一样使用它吗?
  • 好消息。这是关于它的信息:stackoverflow.com/questions/6802765/… 所以这取决于如何在 webdriver 库中内部选择元素。这里的底线是技术上不允许在 DOM 元素的 id 中使用空间,应该避免使用。我会认为这是应用程序/库/将 id 赋予该元素的人的糟糕设计
【解决方案2】:

除了实现两个FindElement*,您还可以按如下方式一步完成:

  • CssSelector:

    wait.Until(x => x.FindElement(By.CssSelector("div.ms-rtestate-write.ms-rteflags-0.ms-rtestate-field[id^='Tasrit_'][aria-labelledby$='_inplacerte_label']>p"))).SendKeys("foo");
    
  • XPath:

    wait.Until(x => x.FindElement(By.XPath("//div[@class='ms-rtestate-write ms-rteflags-0 ms-rtestate-field' and starts-with(@id,'Tasrit_')][contains(@aria-labelledby,'_inplacerte_label')]/p"))).SendKeys("foo");
    

更新

但是元素在我看来是动态的,因此您需要诱导 WebDriverwait 以使所需的元素可点击,并且您可以使用以下任一解决方案:

  • CssSelector:

    new WebDriverWait(driver, TimeSpan.FromSeconds(20)).Until(ExpectedConditions.ElementToBeClickable(By.CssSelector("div.ms-rtestate-write.ms-rteflags-0.ms-rtestate-field[id^='Tasrit_'][aria-labelledby$='_inplacerte_label']>p"))).SendKeys("foo");
    
  • XPath:

    new WebDriverWait(driver, TimeSpan.FromSeconds(20)).Until(ExpectedConditions.ElementToBeClickable(By.XPath("//div[@class='ms-rtestate-write ms-rteflags-0 ms-rtestate-field' and starts-with(@id,'Tasrit_')][contains(@aria-labelledby,'_inplacerte_label')]/p"))).SendKeys("foo");
    

【讨论】:

  • 不错,但结果还是一样。测试通过了,但值并没有真正发送到该字段。
  • @YanivEliav 查看我的答案更新并告诉我状态
  • 就可以了。尽快通知您
  • 由于某种原因,文本(“foo”)被发送到不同的字段,而不是我指向的那个......也许是因为它们有相同的类(?)
  • 有 3 个元素具有相同的类并包含您提到的 id 的相同部分:TextField_inplacerte
【解决方案3】:

如果SendKeys() 不起作用,您可以尝试使用JavaScript

IWebElement webElement = element[2].FindElement(By.TagName("p"));
driver.ExecuteJavaScript("arguments[0].setAttribute('value', 'arguments[1]')", webElement, "foo");

【讨论】:

  • 我也试过了..同样的结果......这是一个尽管如此,毫无疑问
猜你喜欢
  • 1970-01-01
  • 2016-11-25
  • 1970-01-01
  • 1970-01-01
  • 2022-08-10
  • 1970-01-01
  • 2019-08-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多