Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

333
Views
Rails + Jasmine-Ajax: cuál es la forma correcta de probar el código activado por `ajax:success` (jquery-ujs)

Estoy tratando de probar una determinada biblioteca interna que tiene algún comportamiento JS activado en el evento ajax:success .

La biblioteca crea un enlace que se ve así:

 <%= link_to 'click here', '/some_path', class: 'special-link', remote: true %>

Y en la parte JS de la biblioteca hay un código de enlace de eventos, que es la parte que quiero probar en la caja negra a través de su efecto en el DOM :

 $(document).on 'ajax:success', '.special-link', (e, data, status, xhr) -> # Code that has some effect on the DOM as a function of the server response

La biblioteca funciona como se esperaba en el navegador. Sin embargo, cuando trato de probar la biblioteca en Jasmine llamando a $('.special-link').click() , no se puede observar el efecto deseable en el DOM.

El problema, al parecer, es que el evento ajax:success no se activa:

 describe 'my library', -> beforeEach -> MagicLamp.load('fixture') # Fixture library that injects the link above to the DOM jasmine.Ajax.install() jasmine.Ajax.stubRequest('/some_path').andReturn({ responseText: 'response that is supposed to trigger some effect on the DOM'}) afterEach -> jasmine.Ajax.uninstall() # Works. The fixtures are loading properly it '[sanity] loads fixtures correctly', -> expect($('.special-link').length).toEqual(1) # Works. The jquery-ujs correctly triggers an ajax request on click it '[sanity] triggers the ajax call', -> $('.special-link').click() expect(jasmine.Ajax.requests.mostRecent().url).toContain('/some_path') # Works. Code that tests a click event-triggering seems to be supported by Jasmine it '[sanity] knows how to handle click events', -> spy = jasmine.createSpy('my spy') $('.special-link').on 'click', spy $('.special-link').click() expect(spy).toHaveBeenCalled() # Does not work. Same code from above on the desired `ajax:success` event does not work it 'knows how to handle ajax:success events', -> spy = jasmine.createSpy('my spy') $('.special-link').on 'ajax:success', spy $('.special-link').click() expect(spy).toHaveBeenCalled()

¿Cuál es la forma correcta de probar el efecto en el DOM del código que se ejecuta en ajax:success ?

over 4 years ago · Santiago Trujillo
3 answers
Answer question

0

¿Has intentado simplemente espiar la función ajax ? Para eso, necesita usar spyOn y obligarlo a llamar al controlador de eventos success . Eso le permitirá probar lo que espera que suceda cuando se llame.

 it 'knows how to handle ajax:success events', -> spyOn($, "ajax").and.callFake( (e) -> e.success({}); ) $('.special-link').click() # expect some method to be called or something to be changed in the DOM
over 4 years ago · Santiago Trujillo Report

0

Así es como manejaríamos este tipo de cosas en mi equipo.

 it 'knows how to handle ajax:success events', -> spyOn($.fn, 'on'); $('.special-link').click() expect($.fn.on).toHaveBeenCalledWith('ajax:success', '.special-link' some_func);

Este patrón también se extiende bien para probar otros eventos 'encendidos'. Digamos que tenemos algo de jQuery como este:

 $document.on('myCustomEvent', '.some_selector', somecode.custom_func); $document.on('ajax:error', '.some_selector', somecode.failure_func);

Entonces podemos probarlo usando este patrón:

 beforeEach -> spyOn($.fn, 'on'); somecode.init();

Probando una falla de Ajax

 it('indicates failure after ajax error', -> expect($.fn.on).toHaveBeenCalledWith('ajax:error', '.some_selector', somecode.failure_func);

La prueba de Ajax fue llamada desde un evento personalizado

 it('indicates ajax call from custom event', -> expect($.fn.on).toHaveBeenCalledWith('myCustomEvent', '.some_selector', somecode.custom_func);
over 4 years ago · Santiago Trujillo Report

0

Después de mucha depuración, encontré una solución.

Cuando publiqué mi pregunta, cometí 3 errores críticos.

Error #1: la ruta jasmine.Ajax.stubRequest no es relativa

La llamada Ajax no se interrumpió correctamente, ya que la ruta no debería ser la relativa /some_path sino la absoluta http://localhost:3000/some_path cuando se prueba desde el navegador.

En otras palabras, en lugar de:

 jasmine.Ajax.stubRequest('/some_path')

Debería haber usado la versión regexp:

 jasmine.Ajax.stubRequest(/.*\/some_path/)

Error #2: jasmine.Ajax.andReturn debe incluir cotentType

En vez de:

 jasmine.Ajax.stubRequest(/.*\/some_path/).andReturn({ responseText: 'response that is supposed to trigger some effect on the DOM'})

Yo debí haber hecho:

 jasmine.Ajax.stubRequest(/.*\/some_path/).andReturn({ contentType: 'text/html;charset=UTF-8', responseText: 'response that is supposed to trigger some effect on the DOM'})

Sin él, se activa ajax:error en lugar de ajax:success , con un parseerror .

Error n.º 3: el controlador ajax:success se llama asíncrono

Estas líneas de código:

 spy = jasmine.createSpy('my spy') $('.special-link').on 'ajax:success', spy $('.special-link').click() expect(spy).toHaveBeenCalled()

no funcionan, ya que el controlador ajax:success que llama a spy() se llama de forma asíncrona después de alcanzar expect(spy).toHaveBeenCalled() . Puede leer más sobre esto en la documentación de Jasmine .

Poniendolo todo junto

Este es el código que funciona, centrándose solo en la última declaración it que era la intención principal detrás de la pregunta original:

 describe 'my library', -> beforeEach -> MagicLamp.load('fixture') # Fixture library that injects the link above to the DOM jasmine.Ajax.install() jasmine.Ajax.stubRequest(/.*\/some_path/).andReturn({ contentType: 'text/html;charset=UTF-8', responseText: 'response that is supposed to trigger some effect on the DOM'}) afterEach -> jasmine.Ajax.uninstall() # Restructuring the original `it` statement to allow async handling describe 'ajax:success event handling', -> spy = jasmine.createSpy('spy') # Ensures no `it` statement runs before `done()` is called beforeEach (done) -> $('.special-link').on 'ajax:success', -> spy() done() $('.special-link').click() it 'knows how to handle ajax:success events', -> expect(spy).toHaveBeenCalled()

Espero que esto ayude a otros.

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!