Welcome back to the Tower.js tutorial. Using BDD, a style of test-driven development, we are building an app with Tower.js that will log messages in an irc channel and publish those as Github Gists. By the time we are through, you should be quite comfortable with the basics of working with tower, and ready to take on apps of your own. If you are just now joining us, please start out with part 1 so that you will be ready for these steps. Don’t worry, we’ll wait right here for you to catch up!
In the last part of this tutorial, we generated some scaffolds (pre-made sets of views/controllers/models with default routing built in), and then fixed up the tests that came with those. Despite being a bit of work to get those running green, we now have tests covering much of the basic functionality of our models and controllers. That is a good thing. It means as we work, we can have confidence that changes we make aren’t messing something fundamental up.
Today, we’re going to fill in the functionality of those scaffolds, so that the logs our ircbot makes will get recorded as “messages” and then when there are a few of those (ten actually), we’ll use the messages to create our gists and post them to github. Remember to restart both our cake task and mocha tests with:
Now let’s get started.
As before, testing the ircbot’s response to messages sent in an irc chatroom is a bit more complex than we really want to get into here. Since the point of the tutorial is about making apps with Tower.js, and not about building irc servers, we’re going to gloss over those a little bit. Modify the file app/models/ircBot.coffee to look like this:
This adds the message listener to the init method. If you look at what it’s doing, it is pretty simple. We add a listener to the bot for any messages passed in the channel. When the channel emits one of these events, the bot makes a new “message” object, sets the properties on the object to be the user and their message, and then saves it. We could also have used “build” here, and done the object construction slightly differently. You can remove the logging if you want, but you might want to leave it in until after we’ve determined it to be working, in case anything isn’t working.
While I was working on this bit of code, I briefly got a failing test, which immediately ran again and went back to passing. If this happens to you, it’s nothing to be alarmed about (as long as tests begin passing again), it just means that while putting in the code, we accidentally disrupted the flow of the tests.
Checking the Count
Now, back to writing some tests of our own. Open up the file test/models/messageTest.coffee and add this code down beneath where it says ‘describe “relations”‘:
You’ll immediately have a failing test or two again. If you remember from before, sinon is a library we use to make testing easier. It wraps a method for us, in a spy object, which can then provide our tests with information about how that method gets used. In this case, we are checking that upon saving a new message, it calls the checkCount method, which we’ll now write. In app/models/message.coffee, add the additional code you see here.
First, we tell it that after an instance is created, it needs to call the checkCount method. Then in the checkCount method, we literally check the message count. If its over ten, we call the “gistify” method, which we haven’t written yet.
Tests are passing, let’s make them fail again. Back in messageTest.coffee, beneath our last test, add:
We could have written this test in a number of ways, but this seemed the most straightforward. At least it did, until I had to add the setTimeout which I’ll explain momentarily. What we do here is just set a standard loop up to quickly create 11 messages. Then we use a spy to see if the “gistify” method gets called. The problem was that, due to the asynchronous nature of coffeescript, the spy was getting checked while loop was still running, so I simply set a timeOut on that check, to give the loop a few milliseconds to complete. A more correct way would be to somehow use “process.nextTick,” or some kind of callback, but again, mostly owing to my naivety as a noob, I wasn’t able to get the test working properly using either of those. I definitely welcome your suggestions in the comments, as this feels really hacky and ugly to me. If you get a cleaner version of this test working, please let me know so I can refactor my code, and the tutorial.
Now, let’s get this test passing. Go back to message.coffee and alter it to look like so: