ruby on rails - ¿Por qué mi prueba Capybara/Poltergeist no puede seleccionarse desde un campo de autocompletar jQuery?
ruby-on-rails rspec (5)
Tuve este problema y ninguna solución propuesta podría resolverlo. Mis pruebas siempre fallaron al intentar encontrar el elemento ul.ui-autocomplete
. Finalmente me di cuenta de que jQuery Autocomplete agrega el ul
al final de la página html y NO al campo de entrada en cuestión. En mi especificación, sigo la práctica de dirigir mis formularios de forma explícita within my_form do
y haciendo todas las cosas de fill_in
dentro de este bloque:
within my_form do
fill_autocomplete …
end
Por supuesto, esto nunca podría encontrar el ul
adjunto FUERA de este elemento de formulario. Mi solución fue simple: use el atributo de autocompletar de jQuery appendTo: ''#id_of_input_field''
al inicializar la función de autocompletar. Ahora puede encontrar mi ul
y todo funciona bien.
ACTUALIZACIÓN: He solucionado este problema después de mucho trabajo minucioso por mi cuenta. Me complace ser un recurso para cualquiera que necesite ayuda con esto. Aquí está una esencia de mi configuración de trabajo.
He probado todas las soluciones que pude encontrar en Google y SO. Aquí hay algunas cosas diferentes que he intentado:
page.execute_script %Q{$(''#{selector}'').val(''#{value}'').trigger(''keydown'')}
y
fill_in field, with: options[:with]
page.execute_script %Q{ $(''##{field}'').trigger(''focus'') }
page.execute_script %Q{ $(''##{field}'').trigger(''keydown'') }
Esto es lo que falla:
page.should have_selector(''ul.ui-autocomplete li.ui-menu-item a'')
Pero definitivamente está ahí cuando lo miro en Firebug y lo pruebo en el navegador.
Aquí están todos los detalles, incluida una reexpresión de los anteriores. Recuerde, el campo de autocompletar funciona bien en el navegador.
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 %>
y el Coffeescrito:
$("#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)
Los controladores de JS generalmente son malos, son lentos y no son únicos, uno de ellos cubre el 100% de las funciones, y a menudo son extravagantes y difíciles de depurar, pero estoy seguro de que ya lo han resuelto.
Tengo un código similar trabajando en Rails 3.2, minitest y poltergeist 1.3.0 (un menú desplegable ajaxed) pero se rompe de forma periódica sin una buena razón (¿podría decirse que tiene un poltergeist? Ya he recurrido a cambiar esa prueba entre el selenio y el poltergeist un par de veces hasta ahora), no estoy seguro de por qué el autocompletador no funcionaría para usted, pero se siente como un error,
envíe el problema a https://github.com/jonleighton/poltergeist (ya lo tiene? https://github.com/jonleighton/poltergeist/issues/439 ), intente cambiar a selenio o webkit, vea si funciona, puede utilice un controlador diferente en esta prueba si lo saca de la rutina (es mejor que perder días de trabajo en un widget que funciona).
Pude probar mi campo de autocompletado con Poltergeist sin muchos problemas. Lo más importante que .native.send_keys
saber es el método .native.send_keys
de Poltergeist.
Hackear juntos un resumen de los pasos de Cucumber donde estas líneas de código realmente viven en mi proyecto:
find(''#username'').native.send_keys "the" # this field autocompletes usernames
wait_until { all(''a'', text: "the_username").any? }
find(''a'', text: "the_username").click
Luego envío el formulario y afirmo los resultados esperados en la página siguiente de la manera habitual.
wait_until
( una reimplementación de un método que se eliminó de Capybara 2 ) toma un bloque que devuelve verdadero cuando deberíamos dejar de esperar. Es más rápido que esperar 5 segundos o lo que sea cada vez.
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
He encontrado varias soluciones en línea, ninguna de las cuales funciona con las versiones actuales de Poltergeist, Capybara y Autocompletar. Pero aprendí lo suficiente de ellos para hacer un método de ayuda de trabajo, sin llamadas al sueño.
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
Ejemplo de uso:
fill_autocomplete(
''#contact_filter_company'',
listing_page,
with: ''acm'',
select: ''Acme''
)
Tengo un argumento de page
porque estoy usando SitePrism ; si no lo está, puede quitarlo .
Estoy usando esto con:
- jQuery UI Autocomplete 1.11.2
- poltergeist 1.5.1
- capibara 2.4.4
- rspec 3.1.0
Creo que tal vez necesites una mezcla de activar KEYDOWN, pero también establecer el código clave en ABAJO.
p.ej
var keyEvent = $.Event("keydown");
keyEvent.keyCode = $.ui.keyCode.DOWN;
$("#autocomplete").val("j");
$("#autocomplete").trigger(keyEvent);
Aquí hay un ejemplo de jsfiddle que muestra un elemento seleccionado por la función autocompletar: http://jsfiddle.net/alexkey/74BST/ No estoy seguro de por qué tiene que desencadenar la tecla dos veces, pero ese es un problema para resolver por separado (si es un problema) en absoluto).
Sin embargo, no estoy familiarizado con el marco de pruebas de unidad que está utilizando, pero espero que lo anterior ayude.
El crédito va a JQuery AutoComplete, selecciona manualmente el primer elemento buscado y haz clic en clic
Estoy usando el formulario de código de ejemplo: http://api.jqueryui.com/autocomplete/#entry-examples
La unidad de autocompletar prueba que el equipo de jquery-ui usa puede ser útil como inspiración: https://github.com/jquery/jquery-ui/tree/master/tests/unit/autocomplete
También una referencia al código clave: http://api.jqueryui.com/jQuery.ui.keyCode/