I am trying to test a certain internal library that has some JS behavior triggered on the ajax:success
event.
The library creates a link that looks like this:
<%= link_to 'click here', '/some_path', class: 'special-link', remote: true %>
And in the JS part of the library there is event binding code, which is the part I want to black-box test through its effect on the 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
The library works as expected in the browser. However, when I try to test the library in Jasmine by calling $('.special-link').click()
, the desirable effect on the DOM cannot be observed.
The issue, it seems, is that the ajax:success
event does not get triggered:
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()
What is the right way to test the effect on the DOM of code that runs in ajax:success
events?
2 Answers
Answers 1
Have you tried simply spying on the ajax
function? For that, you need to use spyOn
and force it to call the success
event handler. That will let you test what you expect to happen when it's called.
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
Answers 2
Here's how we would handle this sort of thing on my team.
it 'knows how to handle ajax:success events', -> spyOn($.fn, 'on'); expect($.fn.on).toHaveBeenCalledWith('ajax:success', '.special-link' some_func);
This pattern extends well to testing other 'on' events, too. Say we have some jQuery like this:
$document.on('myCustomEvent', '.some_selector', somecode.custom_func); $document.on('ajax:error', '.some_selector', somecode.failure_func);
Then we can test it using this pattern:
beforeEach -> spyOn($.fn, 'on'); somecode.init();
Testing an Ajax failure
it('indicates failure after ajax error', -> expect($.fn.on).toHaveBeenCalledWith('ajax:error', '.some_selector', somecode.failure_func);
Testing Ajax was called from custom event
it('indicates ajax call from custom event', -> expect($.fn.on).toHaveBeenCalledWith('myCustomEvent', '.some_selector', somecode.custom_func);
0 comments:
Post a Comment