如何发送基于水豚中元素的 JavaScript

Bod*_*dao 4 ruby capybara selenium-webdriver

我希望在水豚做这样的事情:

browser.execute_script("arguments[0].setAttribute('value', 'value')", element)
Run Code Online (Sandbox Code Playgroud)

上面的行是在 selenium/ruby 上运行的,但是使用带有水豚的 execute_script 只需要 1 个参数(脚本),因此我无法定义我希望在...上执行脚本的元素……有什么想法吗?

Jus*_* Ko 5

选项 1 - 直接调用 Selenium 的 execute_script

最快的解决方案是绕过 Capybara API 并execute_script直接调用 Selenium-WebDriver 的方法。

为此,您需要使用以下方法访问底层 Selenium::WebDriver::Driver:

page.driver.browser
Run Code Online (Sandbox Code Playgroud)

同样,传递给 Selenium 的元素execute_script需要是 Selenium::WebDriver::Element(而不是 Capybara::Node::Element)。这是通过以下方式完成的:

element.native
Run Code Online (Sandbox Code Playgroud)

例如,假设您有一个带有文本字段的页面:

<input value="5" id="field">
Run Code Online (Sandbox Code Playgroud)

然后以下内容将更改字段的值:

element = find('#field')
p element.value
#=> "5"
page.driver.browser.execute_script("arguments[0].setAttribute('value', 'value')", element.native)
p element.value
#=> "value"
Run Code Online (Sandbox Code Playgroud)

选项 2 - 修补 Capybara 以允许参数

如果您需要经常这样做,您可以对 Capybara 的execute_script方法进行猴子补丁以获取参数,将参数转换为 Selenium 对象,然后将其传递给 Selenium-WebDriver 的方法。补丁将是:

require 'capybara'

class Capybara::Session 
  def execute_script(script, *args)
    @touched = true
    driver.execute_script(script, *args)
  end
end

class Capybara::Selenium::Driver 
  def execute_script(script, *args)
    args.map! { |e| e.kind_of?(Capybara::Node::Element) ? e.native : e }
    browser.execute_script(script, *args)
  end
end
Run Code Online (Sandbox Code Playgroud)

这将允许您将 Capybara 元素传递给 sessionexecute_script方法:

element = page.find('#field')
p element.value
#=> "5"
page.execute_script("arguments[0].setAttribute('value', 'value')", element)
p element.value
#=> "value"
Run Code Online (Sandbox Code Playgroud)