I'm teaching myself Coffeescript/node and, of course, the only way to do this is with TDD. That means I'm also teaching myself vows. There are, I think, at least two problems. One is -- where does the asynchronous code to get the HTTP response lie? And the other is -- why won't the server send me a response back? The console displays "Request sent" but it does not display "Request received."
Here is the test file:
vows = require 'vows'
assert = require 'assert'
EventEmitter = require('events').EventEmitter
Server = require('./web').WebServer
Client = require('../lib/client').Client
Request = require('../lib/request').Request
PORT = 8080
SERVER = new Server PORT
SERVER.start()
CLIENT = new Client PORT, 'localhost'
REQUEST = new Request 'GET', '/'
vows
.describe('Sending a request to the server')
.addBatch
'The request is sent':
topic: ->
CLIENT.transmit(REQUEST, @callback)
return
'The response should be what the server sent back': (err, request) ->
body = ""
request.on 'response', (response) ->
response.on 'data', (chunk) -> body += chunk
assert.equal body, /Ooga/
.export(module)
Here is the WebServer object:
Http = require('http')
exports.WebServer = class WebServer
processRequest = (request, response) ->
console.log 'Request received!'
console.log request
response.writeHead 200, {'Content-Type':'text/plain'} #, 'Content-Length':'6'}
response.write 'Ha-ha!'
response.end
constructor: (@port) ->
@server = Http.createServer processRequest
start: ->
@server.listen @port
stop: ->
@server.close()
Next up is the client code - also very simple.
Http = require 'http'
Request = require('./request').Request
exports.Client = class Client
constructor: (@port, @host) ->
@httpClient = Http.createClient @port, @host
@sentence = "I am a Client"
transmit: (request, callback = null) ->
req = @httpClient.request request.method, request.pathName
req.end
console.log "Request sent!"
if callback
callback(null, req)
#req.on 'response', (res) ->
# callback(null, res)
#request.on 'data', (chunk) -> callback(null, chunk)
#callback(null, request)
And finally, the 'request' object.
exports.Request = class Request
constructor: (@method, @pathName) ->
method: ->
@method
pathName: ->
@pathname
responseBody: ->
@body
setResponseBody: (body) ->
@body = body
appendToResponseBody: (chunk) ->
@body += chunk
All this is so simple that I really can't tell why the server doesn't seem to be working. I'm not even worried, yet, about where the asynchronous code should be to get the information back from the server, but I'd like to figure that out too..
Ah, you've made a classic mistake: You wrote
req.end
where you meant
req.end()
So, your request wasn't actually being sent at all, despite your console's claims to the contrary! (I see a response.end
in your code as well.)
Incidentally, Vows test code is pretty, but it's also a complex framework with some subtle gotchas. You may want to try something simpler, like nodeunit.
Oh, and if you really hate parentheses, you can write do req.end
instead of req.end()
, but this isn't a common style.