Question

Despite these two related questions on StackOverflow, I've yet to find an satisfactory answer for this, so I'm posting to find out if there is an accepted best practice among Jasmine-jQuery users.

The basic problem is simple and two examples of it are covered in the two linked questions:

  • In my Javascript, there is a setup() function that binds event handlers to various selectors on a page, as in $('#someDiv').click(someHandler); this function is passed to $(document).ready

  • In my Jasmine tests, I use HTML fixtures representing various extracted parts of the page to test AJAX interactions on those elements (I'm running the jasmine-rails "server" version, where you can view Jasmine test reports in browser)

The problem, of course, is that the selectors to which setup() tries to bind handlers will not exist until after the fixture is loaded. As a result, an event triggered explicitly in a Jasmine test will not be picked up by the DOM element in the fixture, because the function that would have bound that handler already ran at $(document).ready time.

If only Jasmine could somehow delay the call to $(document).ready until after the fixtures were loaded, I'd be golden. But apparently it can't.

From the two StackOverflow questions above, I've gleaned various ways to get around this, all unsatisfactory:

  1. Copy the binding code in setup into the HTML fixture(s) themselves. This is non-DRY and almost certainly will cause the fixtures to drift out of sync with reality, plus the fixtures are supposed to represent unobtrusive JS and therefore not mix code and markup.

  2. Explicitly call the setup function in the test cases that require it. This works in simple cases, but would fail if setup did non-idempotent things.

  3. In setup, use something like $(document).on('click', '#someDiv', someHandler) instead of the code I showed above. (I'm on jQuery 1.10.1.) I actually tried this but it doesn't work: even if the loaded fixture contains an element matching #someDiv, triggering 'click' on that element doesn't result in someHandler being called. Even if it did work, it's messy because (if I understand correctly) the value of this when the handler is called will reflect the element that actually handled the event, not necessarily the one that first received it.

  4. In setup, use something like $('#someDiv').live(someHandler), but live was deprecated as of jQuery 1.7 and removed in 1.9.

Is there some other method I'm missing that doesn't require making changes to working code solely to accommodate the testing environment and that doesn't require violating DRY?

Was it helpful?

Solution

I have an example of DOM manipulation with Jasmine using jasmine-jquery here. You will also see a link in the description therein to a github repo you can clone to provide more insight into how SpecRunner.html orders dependencies. Basically I have my html fixtures with their onclick events followed by a jquery click() all in my jasmine beforeEach(). I then have my test expectations also check the DOM for validation. This may be along the lines of your #2 workaround above.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top