Saturday, July 3, 2010

Intermediate Vows.js + Fab.js

‹prev | My Chain | next›

I got my first vows.js test passing last night. Up today, a few more. Hopefully this will take my understanding from the very beginning stages on into intermediate understanding. Hopefully.

I am still working through a fab.js app named player_from_querystring. Accessed with a query string describing a player in my (fab) game, the app responds with a JSON object describing the player.

The test from yesterday describes getting the player object, with ID, back:
var suite = vows.describe('just_playing').
addBatch({
'with a query string': {
topic: function() {
var player;
function downstream (obj) { if (obj) player = obj.body; }

var upstream_listener = player_from_querystring.call(downstream);

var head = {
url: { search : "?player=foo&x=1&y=2" },
headers: { cookie: null }
};
upstream_listener(head);

return player;
},
'is player': function (player) {
assert.equal (player.id, "foo");
}
}
}).export(module);
That is more verbose that seems ideal with vows, but I am not sure how to slim it down just yet. I set up a downstream app / function that sets the out-of-scope player variable with the value returned to it by the upstream app. The upstream app is the player_from_querystring app that I am testing. If I send in a player, via the querystring, with ID of "foo", then I ought to get back a player object with an ID of "foo".

Given that same "topic" of the player returned from a querystring, I would also like to assert that a uniq ID is present. Something along the lines of:
      'has unique ID': function(player) {
assert.isDefined (player.uniq_id);
}
Running the vows, I get:
cstrom@whitefall:~/repos/my_fab_game$ vows --spec

♢ just_playing

with a query string
✓ is player
✗ has unique ID
TypeError: Object #<an Object> has no method 'isDefined'
at Object.<anonymous> (/home/cstrom/repos/my_fab_game/test/just_playing.js:30:16)
at runTest (/home/cstrom/.node_libraries/.npm/vows/0.4.5/package/lib/vows.js:99:26)
at EventEmitter.<anonymous> (/home/cstrom/.node_libraries/.npm/vows/0.4.5/package/lib/vows.js:72:9)
at EventEmitter.emit (events:42:20)
at /home/cstrom/.node_libraries/.npm/vows/0.4.5/package/lib/vows/suite.js:147:58
at EventEmitter._tickCallback (node.js:48:25)
at node.js:204:9

✗ Errored » 1 honored ∙ 1 errored (0.104s)
Dang. It was worth a try. The vows.js documentation declares support for assert.isUndefined, so I hoped for a isDefined. Ah well. I end up with this instead, which is not all that pretty:
      'has unique ID': function(player) {
assert.notEqual (typeof(player.uniq_id), "undefined");
}
Just to be sure that is legit, I make sure that it fails with player.uniq_. With player.uniq_id, I now have 2 passing tests:
cstrom@whitefall:~/repos/my_fab_game$ vows --spec

♢ just_playing

with a query string
✓ is player
✓ has unique ID

✓ OK » 2 honored (0.093s)
After adding tests for X-Y coordinates, I try a different "topic" (which I still translate into an RSpec context in my mind). This time, I would like to test that this upstream app terminates the connection with no response if a body (non-querystring) is sent. The context for this looks like:
   addBatch({
'POSTing data': {
topic: function() {
var response;
function downstream (obj) { response = obj; }

var upstream_listener = player_from_querystring.call(downstream);
upstream_listener({body: "foo"});

return response;
}
}
})
Again, I am saving the response sent to the downstream (fab) app and returning it as the topic of this batch of vows. After sending in an actual body (e.g. a browser POSTed data to this resource), the response ought to be undefined.

To test this, I add this to the "POSTing data" object:
       'is null response': function (topic) {
assert.isUndefined (topic);
}
Unfortunately, when I run this test, I get an odd failure:
cstrom@whitefall:~/repos/my_fab_game$ vows --spec

♢ just_playing

with a query string
✓ is player
✓ has unique ID
✓ has X coordinate
✓ has Y coordinate
✗ Errored » just_playing: undefined ∙ Asynchronous Error

✗ Errored » just_playing: POSTing data ∙ not fired!
✗ Errored » 4 honored ∙ 1 errored ∙ 1 dropped
Dang it! I really do want to test for undefined here, but vows.js thinks that returning undefined signals the need for a this.callback call. Sigh. For now, I work around this by returning an array from the topic:
   addBatch({
'POSTing data': {
topic: function() {
var response;
function downstream (obj) { response = obj; }

var upstream_listener = player_from_querystring.call(downstream);
upstream_listener({body: "foo"});

return [response];
},

'is null response': function (topic) {
assert.isUndefined (topic[0]);
}
}
})
That works:
cstrom@whitefall:~/repos/my_fab_game$ vows --spec

♢ just_playing

with a query string
✓ is player
✓ has unique ID
✓ has X coordinate
✓ has Y coordinate
POSTing data
✓ is null response

✓ OK » 5 honored (0.096s)
But it is kinda ugly. I will investigate prettifying it a bit tomorrow.

Day #153

No comments:

Post a Comment