Как избежать мерцания спецификаций при использовании Vue с Rails? - PullRequest
0 голосов
/ 03 октября 2019

Недавно мы интегрировали Vue в наше приложение Rails, но это вызывает много мерцающих тестов Capybara / rspec, которые, насколько я вижу, происходят из условий гонки, когда некоторые или все элементы Vue не отображаютсявремя, когда следующее действие / ожидание Капибары начинается или, возможно, становится визуализированным, но каким-то образом затеняет элемент.

Я вижу следующие виды ошибок:

element click intercepted: Element is not clickable at point (392, 641)
    (Session info: headless chrome=77.0.3865.90)
    (Driver info: chromedriver=77.0.3865.40 (f484704e052e0b556f8030b65b953dce96503217-refs/branch-heads/3865@{#442}),platform=Mac OS X 10.14.6 x86_64) (Selenium::WebDriver::Error::ElementClickInterceptedError)

иони:

element click intercepted: Element <input type="submit" name="commit" value="Sign In" data-disable-with="Sign In" class="btn -light -full -solid"> is not clickable at point (272, 37). Other element would receive the click: <div class="site-header__menu__container | container gutter-lg">...</div>
    (Session info: headless chrome=77.0.3865.90)
    (Driver info: chromedriver=77.0.3865.40 (f484704e052e0b556f8030b65b953dce96503217-refs/branch-heads/3865@{#442}),platform=Mac OS X 10.14.6 x86_64) (Selenium::WebDriver::Error::ElementClickInterceptedError)

(возможно, стоит упомянуть, что координаты, данные в случае неудачи этих тестов, отличаются от одной неудачи к следующей)

Учитывая, что элементы Vue начинаются как теги 0-высоты, которыеможет быть, под нашим меню сайта (сам компонент Vue), я думаю эти две ошибки имеют одну и ту же причину - то есть элемент, на который мы нацеливаемся, еще не был (полностью?) обработан, так что я будупросто для краткости покажите код для одного - хотя дайте мне знать, если вы считаете, что я неправ, и я отредактирую или создам новый пост для другого.

IЯ пробовал методы из двух постов, касающихся этой проблемы, насколько я могу - https://engineering.gusto.com/eliminating-flaky-ruby-tests/ и https://thoughtbot.com/blog/write-reliable-asynchronous-integration-tests-with-capybara - но ни один из них, похоже, не оказал большого влияния (хотя я не уверен, чтовместо метода 'посещение' первый осуждает первый, который лежит в основе большинства тестов функций.

Вот соответствующий код функции для первого:

@vcr
@javascript
Scenario: Successfully pledging after something like confirming my account
  Given something like I am on the pledge form
  When I submit a valid pledge
  Then I should land on the HelloSign signature page

Реализованотаким образом:

Given("something like I am on the pledge form") do
  FactoryBot.create(:user, email: test_user_email, password: test_user_password)
  test_user.confirm
  step 'something like I have signed up and confirmed'
  user = User.last
  user.confirm
  login_as(user, scope: :user)
  visit new_pledge_path
end

When("I submit a valid pledge") do
  fill_in('pledge_pledgor_home_postcode', with: 'Up a tree, cutting mistletoe')
  fill_in('First name', with: "Asterix")
  fill_in('Surname', with: "deGaulle")
  fill_in('Phone number', with: '2345678')
  fill_in('Home address', with: 'A quiet village near the fortified Roman camp')
  fill_in('City', with: 'Totorum')

  fill_in('pledge_companies_attributes_0_name', with: 'Circvmbendibvs Wheels')
  fill_in('pledge_companies_attributes_0_number', with: '1')

  # Minor hack to be able to select options given the JS Choices library's obfuscation:
  find('#country-code-select-wrapper .choices').click
  find('#choices--pledge_pledgor_phone_code-item-choice-3').click
  find('#country-select-wrapper .choices').click
  find('#choices--pledge_pledgor_home_country-item-choice-10').click

  # Defocus the dropdowns before submitting:
  find("body").click

  # Need to activate this wrapping block, run once, then remove it when
  # refreshing the cassette. This seems dumb - would be nice to find a better solution
  # accept_alert do

  click_button('Review & Submit') ## unless ENV['IS_CIRCLE'].present?

  # end
end

Сама кнопка не является элементом Vue, но над ней на странице есть несколько других элементов:

<%= form_for @pledge, html: { class: "standard-form | standard-form-base", id: 'pledge-form' } do |f| %>
  <!-- pledge errors - plain html
  <%= render "layouts/components/form_feedback" %>

  <!--  Sub Section Header - again just html -->
  <%= render "layouts/components/sub-section-header.html", content: @new_pledge_page.about_you %>

  <!--  @new_pledge_page is a Contentful Model object that -->
  <%= render "pledge_fields", content: @new_pledge_page.pledge_fields, f: f %>
<% end %>

И часть _pledge_fields.html.erb:

<!--  Group  -->
<div class="form-group">
  <div class="field-group">
    <%= f.label :pledgor_first_name, content.first_name, class: "standard-label" %>
    <%= f.text_field :pledgor_first_name, value: @pf_presenter.forenames_estimate %>
  </div>
</div>

<!--  Group  -->
<div class="form-group">
  <div class="field-group">
    <%= f.label :pledgor_surname, content.surname, class: "standard-label" %>
    <%= f.text_field :pledgor_surname, value: @pf_presenter.surname_estimate %>
  </div>
</div>

<!--  Group  -->
<div class="form-group">
  <div class="field-group | w-2/5" id="country-code-select-wrapper">
    <label class="standard-label" for="country">
      <%= content.phone_code %>
    </label>
    <select_box :opt="{ variant: '-standard -md', id: 'pledge_pledgor_phone_code', name: 'pledge[pledgor_phone_code]', value: '<%= f.object.pledgor_phone_code.presence || "1" %>' }">
      <%= @pf_presenter.country_phone_code_options %>
    </select_box>
  </div>
  <div class="field-group | w-3/5">
    <%= f.label :pledgor_phone_number, content.phone_number, class: "standard-label" %>
    <%= f.text_field :pledgor_phone_number, placeholder: "(000) 000-0000" %>
  </div>
</div>

<!--  Group  -->
<div class="form-group">
  <div class="field-group" id="country-select-wrapper">
    <label class="standard-label" for="country">
      <%= content.country %>
    </label>
    <select_box :opt="{ variant: '-standard -md', id: 'pledge_pledgor_home_country', name: 'pledge[pledgor_home_country]', value: '<%= f.object.pledgor_home_country.presence || "US" %>' }">
      <%= @pf_presenter.country_options(pledge: f.object) %>
    </select_box>
  </div>
</div>

<!--  Group  -->
<div class="form-group">
  <div class="field-group">
    <%= f.label :pledgor_home_address, content.home_address, class: "standard-label" %>
    <%= f.text_field :pledgor_home_address %>
  </div>
</div>

<!--  Group  -->
<div class="form-group">
  <div class="field-group | w-1/3">
    <%= f.label :pledgor_home_city, content.city, class: "standard-label" %>
    <%= f.text_field :pledgor_home_city %>
  </div>
  <div class="field-group | w-2/3">
    <% if @pf_presenter.probably_based_in?('us') %>
    <%= f.label :pledgor_home_postcode, content.zip_code, class: "standard-label" %>
    <% else %>
    <%= f.label :pledgor_home_postcode, content.postcode, class: "standard-label" %>
    <% end %>
    <%= f.text_field :pledgor_home_postcode %>
  </div>
</div>

<% if !@user.campaign %>
  <!--  Sub Section Header  -->
  <%= render "layouts/components/sub-section-header.html", content: content.company_details_subheader %>

  <%= render "company_fields", content: content.company_details, f: f %>
<% end %>

<!--  Sub Section Header  -->
<%= render "layouts/components/sub-section-header.html", content: content.how_much_subheader %>

<!-- :id="pledge_percentage" -->
<!--  Range Slider  -->
<range_slider :opt="{ id: 'pledge_percentage', name: 'pledge[percentage]' }" :min="2" :start="<%= f.object.percentage || 40 %>" :max="100" class="form-block">
</range_slider>

<!--  Sub Section Header  -->
<%= render "layouts/components/sub-section-header.html", content: content.confirmation_subheader %>

<% if !current_user.try :OptedIntoComms__c %>
<div class="<%= 'hidden' if !@pf_presenter.assumed_in_eu? %>" id="js-gdpr-input">
  <div class="form-group">
    <div class="field-group">
      <%= f.check_box :receive_comms, checked: false, disabled: !@pf_presenter.assumed_in_eu? %>
      <%= f.label :receive_comms, "#{content.gdpr_label}", class: "standard-label -checkbox" %>
    </div>
  </div>
</div>
<% else %>
  <%= f.hidden_field :receive_comms, value: true %>
<% end %>

<%= f.hidden_field :id %>

<%= f.submit content.review_submit, class: "btn -light -full -solid", id: "submit-pledge" %>

Некоторые, возможно, соответствующие спецификации из нашего Gemfile:

ruby "2.6.1"
gem "rails", "5.1.6.2"
gem "rspec-rails", "~> 3.7.2"
gem 'webdrivers', '~> 4.1.2'
gem 'selenium-webdriver', '~> 3.142.4'
gem "capybara", "~> 3.22.0"
...