workshopper-wat
v3.0.1
Published
workshopper web application tester
Downloads
26
Readme
workshopper-wat
workshopper web application tester
Screenshots
Inspiration
I needed a wrapper for workshopper-exercise that provided a simple interface to verify exercises where the user would build a web application that responded in a certain way to a request. Lin Clark's demo-workshopper gave me a great starting point, but I needed it to be more flexible than just comparing response bodies byte per byte when I was building my perfschool workshopper.
Install
npm install workshopper-wat --save
Setup
Please add these resource localization strings to your i18n
manifest.
{
"common": {
"exercise": {
"fail": {
"connection": "Error connecting to {{{url}}} ({{{code}}})",
"unverified": "The exercise doesn't seem to have a verified solution!"
}
}
}
}
Usage
To get started, create a workshopper exercise file like the one below.
var wat = require('workshopper-wat');
var exercise = wat(options);
module.exports = exercise;
Your exercise wants the human to create a solution.js
file that listens on a port that will be provided to them. Suppose they come up with the solution found below.
var http = require('http');
var port = process.env.PORT || 7777;
http.createServer(requestHandler).listen(port, '127.0.0.1');
function requestHandler (req, res) {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('E_WELCOME_MAT\n');
}
During verification, workshopper-wat
will make a request against their server, using the port that was passed as process.env.PORT
, and let you verify the output.
When the exercise is solved, rather than display the reference solution.js
file like workshopper-exercise does, workshopper-wat
renders solution.md
following the same rules that are commonly used for problem.md
. That means there's support for solution.en.md
, solution.en.txt
, and all that stuff.
Options
You could ask the human to come up with many different types of responses, maybe even give them a special payload every time that they have to react to. That's where the options
come in.
options.verify
You must pass a verify(t, req, res)
callback that asserts whether the solution completes the exercise successfully or not. The verify
callback is pretty interesting if I may say so myself. It takes three arguments:
t
This is inspired by tape and allows you to run assertions on the response. It has a few convenient methods.
t.pass(message, passed?)
ifpassed
is unset ortrue
, the assertion will passt.fail(message, failed?)
iffailed
is unset ortrue
, the assertion will failt.fpass(id, formats?, passed?)
same ast.pass
, exceptexercise.__(id, formats)
will be usedt.ffail(id, formats?, failed?)
same ast.fail
, exceptexercise.__(id, formats)
will be usedt.group(name)
finds or creates a group of assertions. Useful to categorize and group together a series of assertions.t.groupend()
leaves thet.group
. Note that groups can be "nested", so make sure to close groups if that's not what you wantt.fgroup(id, formats?)
same ast.group
, exceptexercise.__(id, formats)
will be usedt.end(err?)
the exercise will end, if an error was passed it'll be thrownt.error(err?)
an alias fort.end
req
A few data points about the request that was made.
req.url
is the fully qualified URL. Typically something likehttp://localhost:1396/foo
req.port
is the requested port, e.g1396
res
The response object as returned by request.
options.endpoint
By default, /
is requested, but you could set this to /test
, or anything else.
options.request
You can set request
to an object with any options you may want to pass to request. You shouldn't set the URL here so that the port
is handled for you. If you want to query something other than /
, just change options.endpoint
instead.
options.piped
When true
, the output of their solution will be piped to standard output.
options.wait
By default we listen for a port to handle requests. Wait will timeout after the waitTTL
. Supply your own wait if needed.
options.waitTTL
By default the TTL is 10000
milliseconds.
License
MIT