处理陈旧元素异常

Handle StaleElement exception

我有一个 table,其中可以通过选择一些过滤器复选框来刷新数据。可以选择一个或多个复选框,并且在选择每个复选框后,页面上会显示一个微调器。只有在先前的选择刷新 table 后,才能选择后续过滤器。我面临的问题是我一直间歇性地收到 StaleElementException。 这就是我在水豚中所做的 -

  visit('/table-page') # table with default values is displayed

  # select all filters one by one. Wait for spinner to disappear after each selection
  filters.each {|filter| check(filter); has_no_css?('.loading-overlay', wait: 15)}

  # get table data as array of arrays. Added *minimum* so it waits for table
  all('tbody tr', minimum: 1).map { |row| row.all('th,td').map(&:text) }

我很难理解为什么会看到 StaleElementException。 AFAIK Capybara 在给定节点上使用文本方法时使用同步来重新加载节点。有时也会发生 table 数据 returns 陈旧数据(即最后一次过滤器更新之前的数据)

使用 allfirst 禁用任何元素的重新加载 returned(如果您使用 find 元素是可重新加载的,因为查询用于定位元素是完全已知的)。这意味着,如果在代码的最后一行 运行ning 期间页面发生任何变化,您最终将遇到 StaleElement 错误。这在您的代码中是可能的,因为 has_no_css?可以 运行 在叠加层出现之前。一种解决方案是使用 has_css?等待时间很短,在检查覆盖层消失之前检测覆盖层。 has_xxx?方法只是 return true/false 并且不会在最坏的情况下引发错误 has_css?完全错过了叠加层的 appearance/disappearance,并且在指定的等待时间内基本上进入睡眠状态。

visit('/table-page') # table with default values is displayed

# select all filters one by one. Wait for spinner to disappear after each selection
filters.each do |filter| 
  check(filter); 
  has_css?('.loading_overlay', wait: 1)
  assert_no_selector('.loading-overlay', wait: 15)
end

# get table data as array of arrays. Added *minimum* so it waits for table
all('tbody tr', minimum: 1).map { |row| row.all('th,td').map(&:text) }