First up tonight, a bit of messing about with commonjs. It is a part of node.js, which means that it is a part of fab.js. That does not mean that I know much about.
Take
export
and require
, for instance. I think I get what they do—allow library functions to be imported from a separate file into my current code. Seems straight forward, but I have not had need for it myself. Now that I am testing my fab apps, I think I will need it. Last time around, I broke the player_from_querystring
method out into its own fab app in lib/player_from_querystring.js
. In there, I had two exports statements:function player_from_querystring() {I am exporting two things:
// the actual fab app here
}
exports.tests = ( function() {
// returns a list of functions that can be tested
})();
exports.app = player_from_querystring;
tests
and app
. The former goes into my test harness. The latter goes into my my (fab) game:var puts = require( "sys" ).puts,I could have exported the
player_from_querystring = require('./lib/player_from_querystring').app;
// Other fab code
( /^\/comet_view/ )
( init_comet )
( player_from_querystring )
player_from_querystring
directly:exports.player_from_querystring = player_from_querystring;And then imported thusly:
player_from_querystring = require('./lib/player_from_querystring').player_from_querystring;I prefer the fab.js convention of exporting
app
. I want to import a (fab) app, so it feels right.With that out of the way, I am onto trying to test my
player_with_querystring
method. I got a rudimentary test (that this is a unary app) in place on Monday. Now, let's see if I can verify that, given a query string with player information, my unary app produces a player object.This may not be a good first choice for experimentation. It is rather complicated in that it reads from the downstream (closer to the client) app to parse the query string:
function player_from_querystring() {So how to simulate that in the test harness? Well, I am definitely going to need a fake "head" (the request headers):
var out = this;
return function(head) {
if (head && head.url && head.url.search) {
var search = head.url.search.substring(1);
var q = require('querystring').parse(search);
var app = out({ body: {id: q.player, x: q.x || 0, y: q.y || 0} });
if ( app ) app();
}
else {
out();
}
};
}
exports.tests = ( function() {But how to get that in there? If I execute
var head = { url: { search : "?player=foo&x=1&y=2" } };
return [
function
bodyRespondsWithCorrectPayload() {
// Test goes here
}
];
})();
player_from_querystring
, it is going to return that downstream listener for the header. So I need to call
player_from_querystring
with something that can receive the response. In fab, it is the downstream app that receives the response. I create a fake downstream app to capture the player returned:var player;I am cheating a bit by manipulating player in that downstream app. There is almost certainly a cleaner way to do this, but... I am just trying to get this to work. With that, I want to
function downstream (obj) {
if (obj) player = obj.body;
}
call
player_from_querystring
with that downstream function:var listener = player_from_querystring.call(downstream);That
listener
is what player_from_querystring
returns to get the request headers (and the request body if there is one). This is where I need to pass in my head
with the query string:listener(head);Last, but not least, I need to call the test harness with a boolean value indicating test pass / failure. I try comparing Javascript objects but fail. Instead I try comparing the
id
attribute, which should be "foo":out(player.id == "foo");Altogether my test now reads:
exports.tests = ( function() {And, when I run the tests:
var head = { url: { search : "?player=foo&x=1&y=2" } };
return [
function
statusReturnsUnaryApp() {
this( player_from_querystring().length === 1 );
},
function
bodyRespondsWithCorrectPayload() {
var out = this;
var player;
function downstream (obj) {
if (obj) player = obj.body;
}
var listener = player_from_querystring.call(downstream);
listener(head);
out(player.id == "foo");
}
];
})();
cstrom@whitefall:~/repos/my_fab_game$ node test.jsYay!
Running 2 tests...
statusReturnsUnaryApp: true
bodyRespondsWithCorrectPayload: true
Done. 2 passed, 0 failed.
It is going to be a while before I am TDDing fab.js applications. But this is definite progress.
Day #115
No comments:
Post a Comment