Skip to content

Instantly share code, notes, and snippets.

@stoyan stoyan/test.js
Created Feb 12, 2013

Embed
What would you like to do?
AsciiDoc unit test
// dependencies where I can see them
var assert = require('assert');
var fs = require('fs');
var jslint = require('jshint').JSHINT;
// buncha vars
var snip, rawsnip, start = false, skipping = false, collecting = false;
var passed = 0, skipped = 0;
var lints = 0, nolints = 0;
// short
var log = console.log;
// JSHint options need to be more relaxed because the book also
// points out bad patterns
var lintopts = {
indent: 2, // 2 spaces for indentation
trailing: true, // disallow spaces at the end of a line
white: true,
plusplus: false, // allows ++ and --
browser: true, // assumes some common browser globals exist
// such as `document`
node: true, // assumes the code can run in node.js
// and globals such as `global` are defined
expr: true, // ok to have expressions that seemingly do nothing
// such as `a; // true` which the samples use to show
// result values
loopfunc: true, // allows definition of a function in a loop
// for educational purposes (in the part about closures)
newcap: false, // allows calling constructors (capitalized functions)
// without `new`, again just for educational purposes
proto: true, // allows using `__proto__` which is great for understanding
// prototypes, although it's not supported in all browsers
};
// read the book one line at a time
fs.readFileSync('book.asc').toString().split('\n').forEach(function(src, num) {
num++;
line = src.trim();
// collect JS snippets
if (line === '[source,js]') {
collecting = start = true;
return;
}
if (start) {
start = false;
if (line.indexOf('////') > 0) {
skipping = true;
return;
}
if (line.indexOf('--//--') === -1) { // new snippet
// --//-- signals this snippet depends on the previous
// used for longer snippets that are broken up by explanation
snip = line.indexOf('++--') === -1 ? '"use strict";\n' : ''; // ++ says "dont use strict"
rawsnip = snip; // we want to lint both raw and instrumented snippets
// so far they are the same
}
return;
}
if (collecting || skipping) {
if (line.indexOf('---------') === 0) { // end of snippet
if (skipping) {
collecting = skipping = false;
skipped++;
return;
}
if (snip.indexOf('/*nolint*/') === -1) {
// lint both instrumented and original snippets
lint(snip);
lint(rawsnip);
lints++;
} else {
nolints++;
}
// run the snippet
exec(snip);
collecting = false;
} else if (!skipping){ // yet another line, instrument and add to the snippet
snip += prep(src, num) + '\n';
rawsnip += src + '\n';
}
}
});
// Add asserts
function prep(l, n) {
var parts = l.split(/;\s*\/\/::/); // "//::" separates expression to execute from its result
var nonspace = parts[0].match(/\S/);
var spaces = nonspace === null ? "" : Array(nonspace.index + 1).join(" ");
parts[0] = parts[0].trim();
if (parts[1]) {
var r = parts[1].split(/\s*(,,|::)\s*/)[0].trim(); // the result may have ,, or ::, ignore what's on the right
// e.g. //:: true,, of course!
// e.g. //:: ReferenceError::Invalid whatever
if (r.indexOf('Error') !== -1) {
// expect //:: Error to throw
return spaces + 'assert.throws(function () {' + parts[0] + '; }, ' + r + ', "error line #' + n + '");';
}
if (r === 'NaN') {
// special NaN case
return spaces + 'assert(isNaN(' + parts[0] + '), true, "error line #' + n + '");'
}
// usual
return spaces + 'assert.deepEqual(' + parts[0] + ', ' + r + ', "error line #' + n + '");';
}
return l;
}
// run a snippet
function exec(snip) {
// muck some stuff up and zap log()
var mock = "function define(){}; function alert(){}; console.log = function(){};";
try {
eval(snip + mock);
passed++;
} catch (e) {
log('------');
log(snip);
log('------');
log(e.message);
process.exit();
}
}
// lint a snippet
function lint(snip) {
// lint the snippet with all the options and have it assume
// assert objext exists
if (!jslint(snip, lintopts, {assert: false})) {
log('------');
log(snip);
log('------');
log(jslint.errors[0]);
process.exit();
}
}
// report
log("passed: " + passed + ', skipped: ' + skipped);
log("linted: " + lints + ', nolints: ' + nolints);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.