Since I didn’t want to perfom all actions sequentially, but I still wanted to have the ability to chain actions, I started using event listeners and callbacks to handle asynchronous requests. Recently, I began exploring the world of promises. If you haven’t used them before, this is a great resource. With promises, we can do things like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
Promises are very powerful, but can we write tests for them? Well, we can, but it takes some effort. Now, we can leave promises in our application untested and hope for the best, but since that’s not our style, we powered through it and learned some stuff about promise testing.
We introduced the concept of JS testing with Konacha in a previous post. Now, how do we add asynchronous capabilities?
Testing that a promise works can be done in different ways. If you are returning the promise in your function, you can always do:
1 2 3 4 5
Notice the done argument. This is what your test uses to know it has succeeded. If the done method is not invoked, your test will fail after a timeout. If you are not returning the promise, you can use sinon stubs to test that the promise returns successfully. Using the promise example at the beginning:
1 2 3 4 5 6
That’s neat, but what I struggled testing was the order of execution. How do I make sure that the code in the then block actually waits for the loading to be done. Again, using the promise example at the beginning, this is what I did:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
The timeout adds a buffer to make sure that your loading takes some time, and your show content function is forced to wait. In our example above, passing an argument to done fails the example with the given error. Also, make sure that your timeout is not too large, otherwise your tests will fail.
It works on a browser, but…
Now, we’ve written some tests to make sure our promise succeeds, and the order of execution is right. Everything seems perfect when we run our konacha tests in our browser. However, if you run it in a console, it fails. Why?!?
Well, it seems like some headless browsers, like PhantomJS, do not support promises yet, at all. So, you can either require es6-promise, or you can copy it in a vendor file in your tests, and use that instead. Then, everything should work!