Pretty new to meteor, velocity and jasmine so not sure if I am doing something wrong, using Jasmine for something it's not designed for, or this is just the way it works.
I am finding I need to set timeouts for pretty much all of my tests in order to get them to pass. Should this be the case or am I doing something incorrectly?
For example some tests I am running to check validation messages:
describe("add quote validation", function() {
beforeEach(function (done) {
Router.go('addQuote');
Tracker.afterFlush(function(){
done();
});
});
beforeEach(waitForRouter);
it("should show validation when Quote is missing", function(done) {
$('#quote').val('');
$('#author').val('Some author');
Meteor.setTimeout(function(){
$('#addQuoteBtn').click();
}, 500);
Meteor.setTimeout(function(){
expect($('.parsley-custom-error-message').text()).toEqual("Quote can't be empty.");
done();
}, 500);
});
}
OK, we've had this exact same problem and devised a pretty elegant solution to it, that doesn't require timeouts and is the fastest way to run your tests. Basically, we use one of two strategies, depending on what screen elements you're waiting for.
All code goes into tests/mocha/client/lib.coffee, not 100% what the Jasmine equivalent is, but it should be available to all client test code. I've left it in Coffeescript, but you can compile it on coffeescript.org into Javascript, it should work fine as well.
If whatever you do (routing or something else like changing a reactive variable) causes a
Template
to (re)render, you can use theTemplate.<your_template>.rendered
hook to detect when it is finished rendering. So, we've added the following function in lib.coffee:What does it do? It basically "remembers" the original
rendered
callback and temporarily replaces it with one that calls an extra function after thetemplate
is rendered and the original callback is called. It needs to do this sort of housekeeping to avoid breaking any code that may have depended on therendered
callback, as you're basically messing with the Meteor code directly.In your test, you can then do something like this:
I'd recommend the try-catch as well, as I've noticed asynchronous errors don't always make it into the velocity system, merely giving you a timeout failure.
OK, then there are things that don't actually re-render, but are generated with JS or by some kind of "show/hide" mechanism. For that, you do need some kind of timeout, but you can reduce the "time cost" of the timeout by using a polling mechanism.
You can remove the console logging and secondary
it
iterator function if you like, they're not important. This allows you to do something like this in your test:You can remove the second function if you want, it is the
it
iterator function mentioned above. However, do note that this particular code works with "display: hidden" as the marker for invisibility (Bootstrap does this). Change it if your code uses another mechanism to hide/show parts.Works like a charm for us!