Почему мой тест Capybara/Poltergeist не может быть выбран из поля автозаполнения jQuery?


ОБНОВЛЕНИЕ: Я исправил эту проблему после многих кропотливых работ самостоятельно. Я счастлив быть ресурсом для всех, кому нужна рука. Вот суть моей рабочей настройки.


Я пробовал каждое решение, которое мог найти Google и SO. Вот несколько разных вещей, которые я пробовал:

page.execute_script %Q{$('#{selector}').val('#{value}').trigger('keydown')}

и

fill_in field, with: options[:with]
page.execute_script %Q{ $('##{field}').trigger('focus') }
page.execute_script %Q{ $('##{field}').trigger('keydown') }

Это то, что не удается:

page.should have_selector('ul.ui-autocomplete li.ui-menu-item a')

Но это определенно есть, когда я смотрю на него в Firebug и тестирую его в браузере.

Ниже перечислены все детали, в том числе переформулировка приведенных выше. Помните, что поле автозаполнения отлично работает в браузере.

listing_integration_spec.rb

require "spec_helper"

describe "Listing Integration" do

  let!(:user) { login_user }

  it "lets a user add information listing", js: true do
    listing = create(:listing, user: user)
    click_link('Additional Information')
    click_link('Create')
    fill_autocomplete('listings_search', with: listing.item_id)
  end

end

spec/support/feature_helper.rb

def fill_autocomplete(field, options = {})
  fill_in field, with: options[:with]
  page.execute_script %Q{ $('##{field}').trigger('focus') }
  page.execute_script %Q{ $('##{field}').trigger('keydown') }
  selector = %Q{ul.ui-autocomplete li.ui-menu-item a:contains('#{options[:with]}')}
  page.should have_selector('ul.ui-autocomplete li.ui-menu-item a')
  page.execute_script %Q{ $("##{selector}").trigger('mouseenter').click() }
end

ERB from view template

<%= simple_fields_for :listings  do |f| %>
  <%= f.input :search, label: "Search by Listing", required: true %>
<% end %>

и Coffeescript:

$("#listings_search").autocomplete
  source: (request, response) ->
    options = 
      term: request.term
    $.get "/search_listings", options, (data) ->
      if data.length == 0
        alert "No listings found."
      response data
  minLength: 2
  select: (event, ui) ->
    add_listing_hash = 
      type: "GET"
      url: "/add_listing"
      data: { id: ui.item.id }
      success: () ->
    $.ajax(add_listing_hash)

Ответы

Ответ 1

Драйверы JS, как правило, meh, они медленные, и ни одна из них не покрывает 100% функции, и они часто изворотливы и трудно отлаживаются, но я уверен, что вы уже поняли это.

У меня есть аналогичная часть кода, работающая на рельсах 3.2, minitest и poltergeist 1.3.0 (ajaxed dropdown), но это периодически прерывается без уважительной причины (можно сказать, что у него есть полтергейст? Я уже прибегал переключение этого теста между селеном и полтергейстом пару раз до сих пор), не знаю, почему автозапуск не сработает для вас, но он чувствует себя как ошибка,

отправить вопрос в https://github.com/jonleighton/poltergeist (у вас уже есть? https://github.com/jonleighton/poltergeist/issues/439), попробуйте перейти на селен или веб-кит, посмотрите, работает ли он, вы можете использовать другой драйвер в этом одном тесте, если он вытащит вас из леса (он бьет, теряя дни работы над виджетами, которые работают).

Ответ 2

Я нашел несколько решений в Интернете, ни одна из которых не работает с текущими версиями Poltergeist, Capybara и Autocomplete. Но я достаточно усвоил их, чтобы сделать рабочий помощник, без вызовов сна.

def fill_autocomplete(css_id, page, options = {})
  find("#{css_id}").native.send_keys options[:with]
  page.execute_script %{ $('#{css_id}').trigger('focus') }
  page.execute_script %{ $('#{css_id}').trigger('keydown') }
  selector = %{ul.ui-autocomplete li.ui-menu-item:contains("#{options[:select]}")}
  expect(page).to have_selector('ul.ui-autocomplete li.ui-menu-item')
  page.execute_script %{ $('#{selector}').trigger('mouseenter').click() }
end

Пример использования:

fill_autocomplete(
  '#contact_filter_company',
  listing_page,
  with:   'acm',
  select: 'Acme'
)

У меня есть аргумент page, потому что я использую SitePrism - если вы этого не сделали, вы можете его отключить.

Я использую это с помощью:

  • Автозаполнение jQuery UI 1.11.2
  • poltergeist 1.5.1
  • capybara 2.4.4
  • rspec 3.1.0

Ответ 3

Я смог проверить свое текстовое поле автозаполнения с помощью Poltergeist без особых проблем. Главное знать - метод Полтергейст .native.send_keys.

Взламывая резюме из шагов Cucumber, где эти строки кода действительно живут в моем проекте:

find('#username').native.send_keys "the" # this field autocompletes usernames
wait_until { all('a', text: "the_username").any? }
find('a', text: "the_username").click

Затем я отправлю форму и утвержу ожидаемые результаты на следующей странице обычным способом.

wait_until (повторная реализация метода, который был удален из Capybara 2) берет блок, который возвращает true, когда мы должны перестать ждать. Это быстрее, чем ждать 5 секунд или что угодно каждый раз.

def wait_until(delay = 1)
  seconds_waited = 0
  while ! yield && seconds_waited < Capybara.default_wait_time
    sleep delay
    seconds_waited += 1
  end
  raise "Waited for #{Capybara.default_wait_time} seconds but condition did not become true" unless yield
end

Ответ 4

Я думаю, вам, возможно, нужна комбинация запуска KEYDOWN, но также установка кода ключа DOWN.

например.

var keyEvent = $.Event("keydown");
keyEvent.keyCode = $.ui.keyCode.DOWN;  

$("#autocomplete").val("j");       

$("#autocomplete").trigger(keyEvent);

Вот рабочий пример jsfiddle, показывающий элемент, выбранный автозаполнением: http://jsfiddle.net/alexkey/74BST/ Я не уверен, почему вам нужно запускать keydown дважды, но это проблема для решения отдельно (если проблема вообще).

Однако я не знаком с используемой платформой тестирования модулей, но надеюсь, что это поможет.

Кредит переходит на JQuery AutoComplete, вручную выберите первый элемент поиска и привяжите клик.

Я использую примерную форму кода: http://api.jqueryui.com/autocomplete/#entry-examples

Блок автозаполнения проверяет, что использование команды jquery-ui может оказаться полезным для вдохновения: https://github.com/jquery/jquery-ui/tree/master/tests/unit/autocomplete

Также ссылка на код ключа: http://api.jqueryui.com/jQuery.ui.keyCode/

Ответ 5

У меня была эта проблема, и никакое предлагаемое решение не могло ее решить. Мои тесты всегда терпели неудачу при поиске элемента ul.ui-autocomplete. Наконец, я заметил, что автозаполнение jQuery добавляет ul в конец html-страницы и НЕ к соответствующему полю ввода. В моей спецификации я следую практике таргетинга на мои формы явно within my_form do и выполняя все элементы fill_in внутри этого блока:

within my_form do
  fill_autocomplete …
end

Конечно, это никогда не могло найти прикрепленный элемент ul в этом элементе формы OUTSIDE. Мое решение было простым: использовать атрибут autocomplete jQuery appendTo: '#id_of_input_field' при инициализации автозаполнения. Теперь он может найти мой ul, и все работает нормально.