Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

338
Visualizações
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 Respostas
Responde à pergunta

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 Relatório

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 Relatório

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 Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda