如何从 Capybara/Poltergeist 测试中触发 JQuery 'change' 函数

How to trigger a JQuery 'change' function from a Capybara/Poltergeist test

在表单中,我们有以下 select 字段:

<select class="hundred js-select2 js-country-check select2-hidden-accessible" name="pledge[pledgor_home_country]" id="pledge_pledgor_home_country" tabindex="-1" aria-hidden="true">
  <option value="GB">United Kingdom</option>
  <option value="US">United States</option>
  <option value="DE">Germany</option>
  <option value="AU">Australia</option>
  <option value="BR">Brazil</option>
  <option value="BG">Bulgaria</option>
  <option value="CA">Canada</option>
  <option value="CN">China</option>
  <option value="DK">Denmark</option>
  <option value="EE">Estonia</option>
  <option value="FI">Finland</option>
  <option value="FR">France</option>
  <option value="HK">Hong Kong</option>
  <option value="IS">Iceland</option>
  <option value="IN">India</option>
  <option value="IE">Ireland</option>
  <option value="IL">Israel</option>
  <option value="KE">Kenya</option>
  <option value="LB">Lebanon</option>
  <option value="LU">Luxembourg</option>
  <option value="NL">Netherlands</option>
  <option value="NO">Norway</option>
  <option value="PL">Poland</option>
  <option value="PT">Portugal</option>
  <option value="SG">Singapore</option>
  <option value="ES">Spain</option>
  <option value="SE">Sweden</option>
  <option value="CH">Switzerland</option>
  <option value="TR">Turkey</option>
</select>

并且我们有一个与之关联的 JQuery 函数:

 $('#pledge_pledgor_home_country').change(function() { //change stuff on the page})

我想在我们的功能测试中对此进行某种检查,因此我尝试了以下变体:

When("I select a non-EU country such as Switzerland") do
  find('#pledge_pledgor_home_country').find('option[value="CH"]').select_option    
  script = "$('#pledge_pledgor_home_country').change();"
  page.execute_script(script)
end

但我无法让它工作 - Capybara#execute_script 方法总是 returns nil,所以我没有得到任何反馈,页面内容也没有' 按预期更改。如果我 save_and_open_page,直接从控制台 运行 行 $('#pledge_pledgor_home_country'),它 returns html <select> 元素而不是 JQuery 对象,我从 运行 在 Chrome 的同一页面上使用相同的脚本。但我不确定这是否与测试问题或无头浏览器中 运行ning 脚本的问题有关。

我也尝试在水豚测试中使用这个脚本:script = "$('#pledge_pledgor_home_country').trigger('change');"。那也没用。

在 Gemfile 中我们有这个:

group :development, :test do
  gem "poltergeist", "~> 1.18.1"
  gem "phantomjs", "~> 2.1.1.0", require: 'phantomjs/poltergeist'
end

我在Rails项目的features/support文件夹下设置了JS驱动:

Capybara.javascript_driver = :poltergeist

Capybara.register_driver :poltergeist do |app|
  Capybara::Poltergeist::Driver.new(app, timeout: 1.day, js_errors: false)
end

Cucumber 功能文件如下所示:

@javascript
@vcr
Scenario: Updating GDPR display by country
  Given I am on the new pledge page # (just loads the page) in question
  When I select a non-EU country such as Switzerland
  ...

目前我不确定还可以尝试什么。有什么(好的)方法可以做到这一点吗?

您正在为您的驱动程序使用 Poltergeist,就 JS/CSS 支持而言,它基本上等同于 7 年前的 Safari 版本(因为 PhantomJS 被放弃)。这导致您的问题有两个可能的原因 - 首先是您的页面中可能有与 PhantomJS 不兼容的现代 JS,这会阻止您的更改处理程序被安装。第二个可能的问题是,在 select 失去焦点之前,可能不会触发 change 事件。

第二个问题最容易测试 - 在 select 选择选项后单击页面上的另一个元素。

第一个问题比较棘手,因为 PhantomJS 没有报告一些不兼容性(比如使用 let/const)并且只是默默地不解析 JS。首先从在您的驱动程序注册 (js_errors: true) 中打开错误开始,这样您就不会主动隐藏错误并修复报告的 JS 错误。然而,真正的解决方案是通过 capybara selenium 驱动程序转向使用 headless chrome 或 firefox,而不是 poltergeist,因此您支持当前 JS/CSS.

关于您的其他问题,execute_script 不会 return 任何结果,但 evaluate_script 会并且如果您希望从您的 JS 获得结果,您应该使用它。然而,在测试中使用 execute/evaluate_script 来解决 "issues" 是一个糟糕的想法,因为您现在正在做用户永远无法做的事情,并且有效地隐藏了您应用中的实际问题。

请注意,根据 select 元素上的 js-select2 class,我假设您实际上有一个 JS 驱动的 select 小部件,它正在替换 select.这为第一个潜在问题提供了更多证据,因为如果正在加载该库,您可能无法使用 select_option - 这是因为 JS 小部件通常隐藏原始元素,使其不可交互,您需要查找并单击组成小部件的各个元素(通常是 ul/li 个元素)。