RSpec + headless Chrome for front-end integration test

末鹿安然 提交于 2021-01-28 11:10:11

问题


I'm trying to test a part of my Rails 5.1 app that makes use of Vue.js. The issue I'm encountering is that, for example when generating a list, the Vue code looks like:

<div v-for="(amenity, idx) in amenities">
  <div class="custom-control custom-checkbox">
    <input type="checkbox" class="custom-control-input" v-bind:id="amenity.text" v-model="checkedAmenities[idx]" :value="amenity.id">
    <label class="custom-control-label" v-bind="{ 'for': amenity.text }" >{{ amenity.text }}</label>
  </div>
</div>

and the actual HTML that this produces once evaluated looks like this:

<div>
  <div class="custom-control custom-checkbox">
    <input id="Air conditioning" class="custom-control-input" value="0" type="checkbox"> <label for="Air conditioning" class="custom-control-label">Air conditioning</label>
  </div>
</div>

I end up getting this error in my specs:

Capybara::ElementNotFound:
  Unable to find visible checkbox "Some amenity" that is not disabled

This is because the amenities are defined in the Vue component but are not output in the HTML until they are parsed by the JS interpreter I believe.

I am trying to test with Chrome Headless. I've created the following chrome_driver.rb file:

Capybara.register_driver(:headless_chrome) do |app|
  capabilities = Selenium::WebDriver::Remote::Capabilities.chrome(
    chromeOptions: { args: %w[headless disable-gpu] }
  )

  Capybara::Selenium::Driver.new(
    app,
    browser: :chrome,
    desired_capabilities: capabilities
  )
end

and in my rails_helper.rb:

require 'selenium/webdriver'

RSpec.configure do |config|
  # ...
  Capybara.javascript_driver = :headless_chrome
end

my RSpec test looks something like this:

scenario 'successfully', js: true do
  # do some things here..

  check('Some amenity')
  click_button 'Next'
  click_link 'Create Listing'

  expect(page).to have_content 'Listing was created successfully!'
end

but as mentioned, the error I get is:

Capybara::ElementNotFound:
  Unable to find visible checkbox "Some amenity" that is not disabled

Any idea how I can get Chrome headless to parse the Vue.js code so that the amenities get populated on the frontend?

Thanks in advance!!


回答1:


Judging by the class names of the wrapping div, custom-control custom-checkbox, I'm pretty certain the issue here isn't that the fields aren't being populated correctly (you can use save_and_open_screenshot to verify that, or output page.html) but rather the actual html <input type="checkbox" ...> element is not actually visible on the page (as the error tells you). This was probably done in order to provide a fancy styling to the checkbox by showing images for the checked/unchecked states. To check the checkbox in that case you have a couple of options. The first option is to figure out what element the user actually needs to click to change the setting, and have Capybara do that. For instance

find(:label, 'Some amenity').click

The cleaner solution, when there is a correctly associated label element, is to tell the check method it's allowed to click the label if it needs to

check('Some amenity', allow_label_click: true)

If you want check, uncheck, and choose to always be allowed to click the associated label when a checkbox/radio button is hidden you can make that the default by setting

Capybara.automatic_label_click = true



回答2:


If your label contains a link it will be clicked and not the check box itself:

check('Some amenity', allow_label_click: true)

You can solve it this way:

check('Some amenity', visible: :hidden)


来源:https://stackoverflow.com/questions/49609406/rspec-headless-chrome-for-front-end-integration-test

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!