Después de cargar una página, tengo un código que se ejecuta, oculta y muestra varios elementos basados en datos devueltos por un xhr.
Mi prueba de integración se parece a esto:
it "should not show the blah" do
page.find('#blah').visible?.should be_true
end
Cuando voy manualmente a la página en el contexto en que se ejecuta esta prueba, #blah no es visible como esperaba. Sospecho que Capybara está mirando el estado inicial de la página (invisible en este caso), evaluando el estado del DOM y fallando la prueba antes de que se ejecute JS.
Sí, configuré el :js => true
bloque de descripción que contiene :)
¡Cualquier idea será muy apreciada! Espero no tener que poner un retraso intencional aquí, que se siente inestable y ralentizará las cosas.
ruby
rspec
capybara
integration-testing
Kevin Davis
fuente
fuente
Respuestas:
Creo que la
find
declaración aquí es la que tiene la espera implícita, por lo que Capybara esperará hasta que el elemento esté en la página, pero no esperará a que se haga visible.Aquí, querrá que Capybara espere a que aparezca el elemento visible, lo que debería ser posible al especificar la
visible
opción:expect(page).to have_selector('#blah', visible: true)
No lo he probado, pero la
ignore_hidden_elements
opción de configuración también podría ser útil aquí, si quisierafind
esperar siempre los elementos visibles.fuente
js:true
en el bloque contenedor para que esto funcione.expect(page).to have_selector('#flash-message', visible: false, text: "Signed in Successfully")
- gracias por publicar esta respuestaEsta es otra forma de hacerlo que funciona perfectamente bien para mí:
find(:css, "#some_element").should be_visible
Especialmente para hallazgos más complejos, como
find(:css, "#comment_stream_list li[data-id='#{@id3}']").should_not be_visible
lo que afirmaría que un elemento se ha ocultado.
fuente
should_not be_visible
No me parece bien que Capybara se ejecutewait_until { base.visible? }
cuando el elemento # está visible? siendo invocado..should_not be_visible
cubiertasdisplay: none
establecidas por jQuery? No parece funcionar para mí.Si desea verificar que un elemento está en la página pero no está visible,
visible: false
no funcionará como podría esperar. Me dejó perplejo un poco.He aquí cómo hacerlo:
# assert element is present, regardless of visibility page.should have_css('#some_element', :visible => false) # assert visible element is not present page.should have_no_css('#some_element', :visible => true)
fuente
should_not
con carpincho, debido a ajaxhave_css
esperará toda la duración del tiempo de espera antes de darse por vencido, porque espera encontrar el elemento. Por ejemplo, tienes que usar enshould have_no_content
lugar deshould_not have_content
.expect(page).not_to have_selector("#some_element", visible: true)
funcionó bien para míjavascript_driver
, sin esperar toda la duración del tiempo de espera.should_not
ahora, ¡lo siento!Utilizando:
Ruby: ruby 1.9.3dev (2011-09-23 revision 33323) [i686-linux] Rails: 3.2.9 Capybara: 2.0.3
Tengo una aplicación Rails en la que hay un enlace que, cuando se hace clic, debe enviar una solicitud de publicación AJAX y devolver una respuesta JS.
Código de enlace:
link_to("Send Notification", notification_path(user_id: user_id), remote: true, method: :post)
La respuesta JS (archivo .js.haml) debe alternar el siguiente div oculto en la página donde existe el enlace:
#notification_status(style='display:none')
Contenido del archivo js.haml:
:plain var notificationStatusContainer = $('#notification_status'); notificationStatusContainer.val("#{@notification_status_msg}"); notificationStatusContainer.show();
Estaba probando mi escenario de enviar una notificación y mostrar el mensaje de estado de la notificación al usuario que usa Cucumber ( gema de cucumber-rails con soporte de Capybara incorporado )
Estaba tratando de probar que el elemento que tiene id: notification_status era visible en una respuesta exitosa en mi definición de paso. Para esto, intenté las siguientes declaraciones:
page.find('#notification_status').should be_visible page.should have_selector('#notification_status', visible: true) page.should have_css('#notification_status', visible: true) page.find('#notification_status', visible: true) page.find(:css, 'div#notification_status', visible: true)
Ninguno de los anteriores funcionó para mí y falló mi paso.De los 5 fragmentos enumerados anteriormente, los últimos 4 fallaron con el siguiente error:
'expected to find css "#notification_status" but there were no matches. Also found "", which matched the selector but not all filters. (Capybara::ExpectationNotMet)'
lo cual fue extraño porque la siguiente declaración pasaba correctamente:
page.has_selector?('#notification_status')
Y de hecho inspeccioné la fuente de la página usando
que apareció
<div style='' id='notification_status'></div>
lo que se esperaba.
Finalmente encontré este enlace capibara afirmar atributos de un elemento que mostraba cómo inspeccionar el atributo de un elemento de manera cruda.
También encontré en la documentación de Capybara para visible? método ( http://rubydoc.info/github/jnicklas/capybara/master/Capybara/Node/Element#visible%3F-instance_method ) siguiente información:
Por lo tanto, llegué a la conclusión de que al probar la visibilidad de un elemento, ¿no confía en los resultados de la visibilidad de Capybara? método cuando se usa un selector de CSS y se usa la solución sugerida en el enlace capibara afirmar atributos de un elemento
Se me ocurrió lo siguiente:
module CustomMatchers def should_be_visible(css_selector) find(css_selector)['style'].should_not include('display:none', 'display: none') end end World(CustomMatchers)
Uso:
should_be_visible('#notification_status')
fuente
Lo que significa visible no es obvio
La falla puede provenir de un malentendido de lo que se considera visible o no, ya que no es obvio, no es portátil para el controlador y está poco documentado. Algunas pruebas:
HTML:
<div id="visible-empty" ></div> <div id="visible-empty-background" style="width:10px; height:10px; background:black;"></div> <div id="visible-empty-background-same" style="width:10px; height:10px; background:white;"></div> <div id="visible-visibility-hidden" style="visibility:hidden;" >a</div> <div id="visible-display-none" style="display:none;" >a</div>
Lo único que Rack test considera invisible es en línea
display: none
(no CSS interno, ya que no hace selectores):!all('#visible-empty', visible: true).empty? or raise !all('#visible-empty-background', visible: true).empty? or raise !all('#visible-empty-background-same', visible: true).empty? or raise !all('#visible-visibiility-hidden', visible: true).empty? or raise all('#visible-display-none', visible: true).empty? or raise
Poltergeist tiene un comportamiento similar, pero puede lidiar con la
style.display
manipulación interna de CSS y Js :Capybara.current_driver = :poltergeist !all('#visible-empty', visible: true).empty? or raise !all('#visible-empty-background', visible: true).empty? or raise !all('#visible-empty-background-same', visible: true).empty? or raise !all('#visible-visibiility-hidden', visible: true).empty? or raise all('#visible-display-none', visible: true).empty? or raise
El selenio se comporta de manera bastante diferente: si considera que un elemento vacío es invisible y
visibility-hidden
ademásdisplay: none
:Capybara.current_driver = :selenium all('#visible-empty', visible: true).empty? or raise !all('#visible-empty-background', visible: true).empty? or raise !all('#visible-empty-background-same', visible: true).empty? or raise all('#visible-visibiility-hidden', visible: true).empty? or raise all('#visible-display-none', visible: true).empty? or raise
Otro problema común es el valor predeterminado de
visible
:false
(ve ambos elementos visibles e invisibles),true
Capybara.ignore_hidden_elements
opción.Referencia .
Prueba completa ejecutable en mi GitHub .
fuente
Es posible que desee ver esta publicación , que brinda un método de muestra para esperar hasta que se completen todas las solicitudes de ajax:
def wait_for_ajax(timeout = Capybara.default_wait_time) page.wait_until(timeout) do page.evaluate_script 'jQuery.active == 0' end end
fuente
wait_until
se eliminó de Capybara 2 .Timeout.timeout
Selenium::WebDriver::Wait
La respuesta aceptada está un poco desactualizada ahora, ya que 'debería' es una sintaxis obsoleta. En estos días, sería mejor que hicieras algo como
expect(page).not_to have_css('#blah', visible: :hidden)
fuente
Las otras respuestas aquí son la mejor manera de "esperar" el elemento. Sin embargo, he descubierto que esto no funcionó para el sitio en el que estoy trabajando. Básicamente, el elemento que necesitaba hacer clic era visible antes de que la función detrás de eso estuviera completamente cargada. Esto es en fracciones de segundo, pero descubrí que mi prueba se ejecutó tan rápido en ocasiones que hizo clic en el botón y no sucedió nada. Me las arreglé para solucionarlo haciendo esta expresión booleana improvisada:
if page.has_selector?('<css-that-appears-after-click>') puts ('<Some-message-you-want-printed-in-the-output>') else find('<css-for-the-button-to-click-again>', :match == :first).trigger('click') end
Básicamente, usa el tiempo de espera predeterminado del capibara para buscar algo que debería aparecer, si no está allí, volverá a intentar hacer clic.
Nuevamente diré que el
should have_selector
método debe probarse primero, pero si simplemente no funciona, intente estofuente