【问题标题】:Can't access text of an element in an array using PageObject and Watir无法使用 PageObject 和 Watir 访问数组中元素的文本
【发布时间】:2016-04-09 04:45:40
【问题描述】:

我有一个我收集的数组:

array= @browser.ul(:class => 'parent').links

然后我尝试访问数组中特定元素上的文本,像这样遍历数组:

array.each_with_index do |i, index|

如果我这样做:

array[index]

我取回了锚元素对象。如果我这样做:

array[index].element

我将取回一个 HTML 元素对象。但是,如果我尝试获取任何特定元素,例如:

array[index].text
array[index].value

然后我收到“无法定位元素”错误。

我正在使用 Watir、Page Object 和 Ruby。

这里是整个数组迭代的范围,比较简单:

array= @browser.ul(:class => 'parent').links
array.each_with_index do |i, index|
  if index == array.length-1
    sleep 1
    @browser.button(:text => 'Complete').when_present.click
  else
    sleep 1
    @browser.button(:text => 'Complete').when_present.click
    @browser.a(:text => 'Next').when_present.click
  end
end

我正在尝试添加一个elsif 来检查链接的文本,以便如果它位于该特定页面/链接上,它会在该页面上执行特定的操作。

例如,在伪代码中:

如果数组元素text = "Instructions",则不要点击完成按钮,直接点击下一步。

我想我愿意以任何方式解决这个问题,让我识别它当前所在的链接,以便我可以执行一组操作,但我认为获取当前链接的文本是最简单的,因此这个问题。

如何访问此数组中元素的文本或特定属性?

【问题讨论】:

  • 在您创建array 和调用array[index] 之间,您是否执行过任何会刷新部分页面的操作?
  • 可能。基本上迭代通过每个链接移动。所以它点击一个“完成”按钮,隐藏页面上的一些东西,然后点击一个“下一步”按钮,将它移动到数组中的下一个链接。然后下一次迭代开始并再次执行。如果有帮助,我可以更新整个数组代码部分。当我尝试数组[索引](我试图找出是否以及如何访问文本)时,它在单击完成按钮步骤时处于调试模式,因此何时应从数组中加载元素。跨度>
  • 欢迎来到 Stack Overflow。请阅读“minimal reproducible example”。只有对问题的描述才能让我们尝试想象您在做什么,但是拥有代码和数据会使它非常明显。我们可以为您提供广泛的答案,但 Stack Overflow 是关于详细答案的。请提供更多信息,包括演示问题所需的最少代码/数据。它不必使用 Watir,只需在代码中重新创建最小结构即可。它可以帮助我们帮助您。
  • 不清楚它到底在哪里失败,哪一行?它可能无法在条件的第二部分中找到 :text => 'Next' ,在第一部分中也可能无法找到 :text => 'Complete' 。另一方面,从逻辑上讲,您缺少其他 else if,它应该在哪里继续。请更新您的问题,并可能给我们一个 URL 或 jsfiddle 它。
  • 它不会在任何这些行上失败。由于特定页面的工作方式,上面的代码失败了,这就是我需要不同条件的原因。问题是如何识别该特定页面上的即时消息。我认为从它所在的数组中的元素中获取文本很容易,但事实并非如此。页面这部分的 HTML 会相当大,但如果人们认为它有助于找到解决方案,我可以添加它。基于这个问题,我不确定 html 是否会有所帮助

标签: arrays ruby watir watir-webdriver page-object-gem


【解决方案1】:

您的元素的 DOM 很可能在一些交互之后发生了变化(例如单击“完成”按钮)。

我的建议是每次交互后重新查找所有元素。

试试这样的:

array = @browser.ul(:class => 'parent').links
index = 0
array.length.times do
  sleep 1
  if index == array.length-1
    @browser.button(:text => 'Complete').when_present.click
    array = @browser.ul(:class => 'parent').links #We are finding new array after possible change
  elsif  array[index].text == 'Instructions'
    @browser.a(:text => 'Next').when_present.click
  else
    @browser.button(:text => 'Complete').when_present.click
    @browser.a(:text => 'Next').when_present.click
  end
  array = @browser.ul(:class => 'parent').links #And once again
  index = index+1
end

注意:我不能保证上面的代码会起作用,因为我没有页面可以确定。如果它不起作用 - 尝试使用这个想法修改它

【讨论】:

  • 那么,像 array[index].text 这样的东西应该拉回元素的文本吗?那是最初的问题,我如何获得文本。如果这应该工作,那么我可以调整如何解决它。当我尝试上述操作时,我处于调试模式,因此它一次在同一页面和同一屏幕上停留几分钟,因此刷新 DOM 应该不是问题,它有足够的时间来重置。
  • 是的。我什至重新检查了它。 array[1].text 给出元素的文本。
  • 这个特定的代码不起作用,但这个概念是正确的答案。我不得不等待页面刷新并在每个非指令页面之后重建数组。到目前为止它的工作。
【解决方案2】:

遍历链接列表并仅提取有关它们的信息非常简单,并且只要 DOM 没有变化就应该可靠地工作。一旦您开始点击内容,或采取导致部分或全部页面更新的操作,所有的赌注都将被取消,因为您的收藏可能包含对 UI 中已删除或替换的元素的引用。

您似乎对 .each 迭代器的工作方式有些困惑。该方法的基本形式依次返回集合中的每个对象。 with_index 版本返回每个对象加上它在数组中的索引。在大多数情况下,除非您关心索引是什么,否则您不会使用 with_index 形式。

例如,要遍历您的集合并输出每个链接的文本,您可以简单地这样做

links_list = @browser.ul(:class => 'parent').links
links_list.each do |link|
  puts "the link text is: #{link.text}"
end

如果你想指出每个链接的索引,那么你可以这样做

links_list = @browser.ul(:class => 'parent').links
links_list.each_with_index do |link, index|
  puts "the text for link number #{index} is: #{link.text}"
end

如果您想按自己的方式处理类似的链接列表并对它们做一些可能导致页面更新的事情,那么您最好使用类似于其他链接的策略回答您根据列表的大小创建循环的位置,但在循环内重新获取列表,以便它始终是“新鲜的”并且不会包含对不再在 DOM 中的对象的引用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-11
    • 1970-01-01
    • 2016-08-08
    相关资源
    最近更新 更多