【问题标题】:How to wait in Capybara when using #all使用#all时如何在Capybara等待
【发布时间】:2016-03-22 13:11:06
【问题描述】:

我知道 wait_until 出于某种原因已从 Capybara 中删除。 Capybara 善于等待,使用find 时等待很好,但是在处理AJAX 应用程序时,有时我不得不使用all 方法。例如,我正在处理一个 HTML 表,我可以通过单击列名对其进行排序。当我对列名应用排序然后调用all(td, text: column_name) 时,它会返回排序之前存在的值,因为all 方法不会像find 方法那样等待。我目前正在使用定制助手wait_for_ajax 来处理这种情况。我不想传递额外的 :wait 参数。有没有更好的处理方法?

【问题讨论】:

    标签: ruby capybara


    【解决方案1】:

    如果你正在测试一个应用程序,那么这相对容易,因为你知道测试数据,所以你可以做类似的事情

    expect(page).to have_css('table tr:first-child', text 'text first in order when sorted')
    

    这将等待表格的第一行具有在排序发生后应首先出现在排序顺序中的文本。

    如果您在不知道测试数据的情况下进行屏幕抓取或测试应用程序,那么这将变得更加困难。当您对列进行排序时,除了行的顺序之外,页面上是否会发生任何变化?是否有排序指示器、排序的列标题突出显示等?如果是这样,您可能可以等待,假设在更新列之前它实际上不会更新(如果它在单击后立即更新,那么这将不起作用,并且实际上可能是一个糟糕的 UI,因为您可以结束数据不一致)。例如,如果列标题获得“排序”类,您可以执行类似

    expect(page).to have_css('table th td.sorted', text: 'text of the column header you sorted by')
    

    它将等待正确的标头指示它已排序。

    如果确实没有任何更改表明排序已完成,那么您就不走运了,您遇到了极少数应该使用诸如 wait_for_ajax 之类的情况之一。

    注意:在这种情况下,传递 :wait 选项对您毫无帮助。这是因为这是等待找到匹配元素的 最大 时间,并且 #all 有效匹配 0 个元素 - 它仍然会立即返回(没有提到的任何计数选项另一个答案,正如您指出的那样,无论如何都对您没有帮助)

    【讨论】:

    • 谢谢汤姆。单击后,列标题确实会得到一个类.sorted。实际上,在这种情况下,我已经在使用 wait_for_ajax 助手。我想我可以等待.sorted,但考虑到在大多数情况下使用 Capybara 时几乎不需要等待,所以当wait_for_ajax 可以完成这项工作时,按照您的建议添加等待可能有点矫枉过正?可能这是不好的做法,但鉴于在很多情况下它变得必要,我发现它通常有效。当必须在页面上使用 all 时,我无需处理个案等待
    【解决方案2】:

    我正在使用它在触发事件之前加载所有 HTML 内容。只要你想指定等待,你就可以调用这个方法

    def wait_for_ajax
      Timeout.timeout(Capybara.default_wait_time) do
        loop do
          active = page.evaluate_script('jQuery.active')
          break if active == 0
        end
      end
    end
    

    【讨论】:

    • default_wait_time 在较新版本的 Capybara 中已弃用 default_max_wait_time。最重要的是 - 使用这样的超时可能会导致破坏一些 Capybara 驱动程序,因为它可能会在 evaluate_script 中间中断并使驱动程序通信堆栈处于未知状态 - 查看 Capybara 中的#synchronize如果你真的需要 wait_for_ajax,那么更安全的方法是 - 虽然 99% 的时间通常是不必要的(OP 可能有 1% 的情况)
    • 谢谢,我已经在用这个了。我想知道是否有更好的方法。
    【解决方案3】:

    这是wait_for_ajax 方法实际上是正确选择的极端情况之一。这是我的实现,它不使用 Tom 建议的 Timeout 可能会导致错误。

    def wait_for_ajax
      start = Time.now.tv_sec
      stop = false
      until stop do
        active = page.evaluate_script('jQuery.active')
        if active == 0
          stop = true
        elsif (Time.now.tv_sec - start) > Capybara.default_max_wait_time
          stop = true
          raise Exception.new("WaitForUrlError: Timed out waiting for url: #{url}")
        end
      end
    end
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-07-31
      • 1970-01-01
      • 1970-01-01
      • 2020-12-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多