The JSON reporter
The JSON
reporter is especially versatile. Since it produces a literal
serialization of the reporter event stream, it can be used to transport reporter
events to another process and format them there. For example, say we build a
WebSocket server that, when a new connection is made, runs our example test
suite as a child process using the json
format, and pipes the
output into the socket.
For example if you open a connection to ws://localhost:8888/?test=foo
this
server will run this process:
jstest -f json example/spec/set_spec.js -t foo
Here’s the server code:
// example/socket/server.js var child = require('child_process'), http = require('http'), url = require('url'), split = require('split'), WebSocket = require('faye-websocket') var bin = 'jstest', argv = ['-f', 'json', 'example/spec/set_spec.js'] var server = http.createServer() server.on('upgrade', function(request, socket, body) { var ws = new WebSocket(request, socket, body), // parse the request's query string params = url.parse(request.url, true).query, tests = JSON.parse(params.test), // construct ARGV for the child process options = tests.reduce(function(o, t) { return o.concat(['-t', t]) }, []), proc = child.spawn(bin, argv.concat(options)) proc.stdout.pipe(split()).pipe(ws) }) server.listen(8888)
Run the server with Node:
$ node example/socket/server.js
This will send a stream of messages over the WebSocket with the format:
{"jstest": [eventType, data]}
jstest
includes a class called JS.Test.Reporters.JSON.Reader
, whose job is
to process this stream of messages and use them to notify another reporter. We
could use it to accept the data from the WebSocket and display the test
results in the browser, like this:
<!-- example/socket/browser.html --> <!doctype html> <html> <head> <meta charset="utf-8"> <title>jstest</title> </head> <body> <script src="../../build/jstest.js"></script> <script> var options = new JS.Test.Runner().getOptions(), R = JS.Test.Reporters, browser = new R.Browser(options), reader = new R.JSON.Reader(browser) var test = encodeURIComponent(JSON.stringify(options.test)), ws = new WebSocket('ws://localhost:8888/?test=' + test) ws.onmessage = function(event) { reader.read(event.data) } </script> </body> </html>
If you open this page, it will open a WebSocket, which will trigger a test
run. The socket will receive the test output as a JSON stream, which it hands
off to the JSON.Reader
, which displays the results with the Browser
reporter. Now you can selectively run your server-side tests from the browser!
You can do a similar thing to send browser results to the terminal by overriding
where the JSON
reporter writes output to. When you run your tests, try this:
var ws = new WebSocket('ws://localhost:8888/'), json = new JS.Test.Reporters.JSON() json.puts = function(message) { ws.send(message) } ws.onopen = function() { JS.Test.autorun(function(runner) { runner.addReporter(json) }) }
This will send the browser results over the socket as JSON, and you can use a
Reader
on the server to print the results in the terminal.