I’m trying to test the following which works manually:
- Return a list of users as
<div>
‘s - Click a button to reduce that count of
<div>
‘s by one.
This does not seem to be working:
it("should show one less person if you tap you liked them", function() { var personLength = $('.person').length; console.log(personLength); #> 7 $("[data-action=like]").first().click(); console.log($('.person').length); #> 7 console.log(Likes.find().fetch()); #> 1 expect($('.person').length).toEqual(person-1); #> Fail (expected 7 to equal 6) });
I’m confused on why it does this. I clearly get the expected result when testing manually.
I think I’m missing some way to reset that test to look at the DOM again or something? Perhaps some async method to callback? I’m not sure but seems like a simple error.
Advertisement
Answer
Keeping reactivity under control
First you should understand how reactivity and Meteor works. The component that manages reactivity is called Tracker (previously Deps). You can read how it works in the Meteor Manual.
Each time you trigger an action that will cause reactive behavior and
you want to test the result of the reactive behavior, you should
call Tracker.flush()
after triggering the action. This will ensure that
all reactive changes are applied before you evaluate your expectations.
When is a Tracker.flush()
call required? (incomplete list)
- After rendering templates with
Blaze.render
andBlaze.renderWithData
- After triggering DOM events
- After changing data in collections
If your expectations fail and you have verified manually that the tested
behavior works, you can try to insert a Tracker.flush()
before your expectations.
For your example this should do it:
beforeAll(function () { var self = this; self.deferAfterFlush = function (callback) { Tracker.afterFlush(function () { Meteor.defer(callback); }); }; }); // Guarantee that tests don't run in a ongoing flush cycle. beforeEach(function (done) { this.deferAfterFlush(done); }); it("should show one less person if you tap you liked them", function() { var personLength = $('.person').length; console.log(personLength); #> 7 $("[data-action=like]").first().click(); Tracker.flush(); console.log($('.person').length); #> 6 console.log(Likes.find().fetch()); #> 1 expect($('.person').length).toEqual(person-1); #> Pass (expected 6 to equal 6) });