4

我有一个 spec/capybara 测试,它搜索一个元素,然后尝试运行一个 JS 脚本来将元素滚动到视图中。但是,Capybara 声称该节点在尝试运行 JS 时已过时。有争议的行是连续的。他们来了:

element = page.find(selector, visible: false)
Capybara.current_session.driver.browser.execute_script(script, element.native)

我已经做了相当多的调试。在findexecute_script行之间放置调试器时,调用element确实会返回一个过时的节点Obsolete #<Capybara::Node::Element>

在调试器中运行page.find(selector, visible: false)不会返回过时的节点,而是您期望的正常活动节点#<Capybara::Node::Element tag="div" path="/HTML/BODY[1]/DIV[6]/DIV[2]/DIV[1]/DIV[1]/DIV[54]">

此外,删除这两行并在调试器中手动运行它们会看到 capybara 正确找到 DOM 元素,正确运行 JS,并且规范通过

相关代码:

  def scroll_to(selector, align = true)
    if align
      script = <<-JS
        arguments[0].scrollIntoView(true);
      JS
    else
      script = <<-JS
        arguments[0].scrollIntoView(false);
      JS
    end

    element = page.find(selector, visible: false)

    Capybara.current_session.driver.browser.execute_script(script, element.native)
  end

  scroll_to(".xdsoft_time[data-hour='13'][data-minute='15']")

4

1 回答 1

1

Without knowing what's happening on your page it's impossible to say exactly why you're getting the 'obsolete node' error, but that error indicates the node that was originally found is no longer in the page. This can happen if you visit a new page, if the part of the page containing that node is replaced by JS, etc.

Passing visible: false and then trying to scroll that element into the page doesn't make sense though since if the element isn't visible then you'll never be able to scroll it into view (visible means drawn on the page, it does not mean 'in the viewport').

Other issues with your code are

  1. you should not be calling the driver specific execute_script, but rather just use the Capybara session execute_script (generally if you're using Capybara.current_session.driver.browser you're doing something wrong).

    page.execute_script(script, element)
    
  2. Capybara already provides a scroll_to so use it instead of writing your own

      page.scroll_to(page.find(selector)) # Defaults to scrolling to the top
    

    If you need control over the alignment of the element just pass the :align option

      page.scroll_to(page.find(selector), align: :center) # :top, :bottom, :center
    
于 2019-10-23T16:43:14.733 回答