Почему мой тест 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
, и все работает нормально.