From 87a882c83459c065e299fee1f27c31097897992c Mon Sep 17 00:00:00 2001 From: Andrew de Andrade Date: Thu, 14 Aug 2014 17:13:28 -0700 Subject: [PATCH] Added t.diag() method to print yaml metadata --- lib/results.js | 74 +++++++++++++++++++++++++++++++--------------- lib/test.js | 5 ++++ package.json | 7 +++-- test/diag.js | 51 ++++++++++++++++++++++++++++++++ test/double_end.js | 2 +- test/undef.js | 6 ++-- 6 files changed, 114 insertions(+), 31 deletions(-) create mode 100644 test/diag.js diff --git a/lib/results.js b/lib/results.js index fa414f47..fdc2261f 100644 --- a/lib/results.js +++ b/lib/results.js @@ -3,6 +3,7 @@ var inherits = require('inherits'); var through = require('through'); var resumer = require('resumer'); var inspect = require('object-inspect'); +var YAML = require('yamljs'); var nextTick = typeof setImmediate !== 'undefined' ? setImmediate : process.nextTick @@ -100,7 +101,11 @@ Results.prototype._watch = function (t) { write('# ' + res + '\n'); return; } - write(encodeResult(res, self.count + 1)); + if (typeof res.ok === 'boolean') { + write(encodeResult(res, self.count + 1)); + } else { + return write(diagDelimiters(YAML.stringify(res, 4))); + } self.count ++; if (res.ok) self.pass ++ @@ -125,48 +130,69 @@ Results.prototype.close = function () { self._stream.queue(null); }; -function encodeResult (res, count) { +function indent(str, spaces) { + return str.split('\n').map(function(line) { + return Array(spaces + 1).join(' ') + line; + }).join('\n'); +} + +function diagDelimiters (yaml) { + var output = '---\n'; + output += yaml; + output += '...\n'; + output = indent(output, 2); + // remove two extra spaces + output = output.slice(0, output.length - 2); + return output; +} + +function errorYAML (res) { var output = ''; - output += (res.ok ? 'ok ' : 'not ok ') + count; - output += res.name ? ' ' + res.name.toString().replace(/\s+/g, ' ') : ''; - - if (res.skip) output += ' # SKIP'; - else if (res.todo) output += ' # TODO'; - - output += '\n'; - if (res.ok) return output; - - var outer = ' '; - var inner = outer + ' '; - output += outer + '---\n'; - output += inner + 'operator: ' + res.operator + '\n'; + output += 'operator: ' + res.operator + '\n'; if (has(res, 'expected') || has(res, 'actual')) { var ex = inspect(res.expected); var ac = inspect(res.actual); if (Math.max(ex.length, ac.length) > 65) { - output += inner + 'expected:\n' + inner + ' ' + ex + '\n'; - output += inner + 'actual:\n' + inner + ' ' + ac + '\n'; + output += 'expected:\n ' + ex + '\n'; + output += 'actual:\n ' + ac + '\n'; } else { - output += inner + 'expected: ' + ex + '\n'; - output += inner + 'actual: ' + ac + '\n'; + output += 'expected: ' + ex + '\n'; + output += 'actual: ' + ac + '\n'; } } if (res.at) { - output += inner + 'at: ' + res.at + '\n'; + output += 'at: ' + res.at + '\n'; } if (res.operator === 'error' && res.actual && res.actual.stack) { var lines = String(res.actual.stack).split('\n'); - output += inner + 'stack:\n'; - output += inner + ' ' + lines[0] + '\n'; + output += 'stack:\n'; + output += ' ' + lines[0] + '\n'; for (var i = 1; i < lines.length; i++) { - output += inner + lines[i] + '\n'; + output += lines[i] + '\n'; } } + + return output; +} + +function encodeResult (res, count) { + var output = ''; + output += (res.ok ? 'ok ' : 'not ok ') + count; + output += res.name ? ' ' + res.name.toString().replace(/\s+/g, ' ') : ''; - output += outer + '...\n'; + if (res.skip) output += ' # SKIP'; + else if (res.todo) output += ' # TODO'; + + output += '\n'; + if (res.ok) return output; + + if (!res.ok && res.operator) { + output += diagDelimiters(errorYAML(res)); + } + return output; } diff --git a/lib/test.js b/lib/test.js index 171eea05..b466ee36 100644 --- a/lib/test.js +++ b/lib/test.js @@ -107,6 +107,11 @@ Test.prototype.comment = function (msg) { this.emit('result', msg.trim().replace(/^#\s*/, '')); }; + +Test.prototype.diag = function (json) { + this.emit('result', json); +} + Test.prototype.plan = function (n) { this._plan = n; this.emit('plan', n); diff --git a/package.json b/package.json index d5f07fc1..4509b597 100644 --- a/package.json +++ b/package.json @@ -15,11 +15,12 @@ "inherits": "~2.0.1", "object-inspect": "~0.4.0", "resumer": "~0.0.0", - "through": "~2.3.4" + "through": "~2.3.4", + "yamljs": "^0.1.5" }, "devDependencies": { - "tap" : "~0.4.8", - "falafel" : "~0.3.1", + "tap": "~0.4.8", + "falafel": "~0.3.1", "concat-stream": "~1.4.1" }, "scripts": { diff --git a/test/diag.js b/test/diag.js new file mode 100644 index 00000000..88b5dde2 --- /dev/null +++ b/test/diag.js @@ -0,0 +1,51 @@ +var tape = require('../'); +var fs = require('fs'); +var cp = require('child_process'); + +var expected = [ + 'TAP version 13', + '# beep', + 'ok 1 should be equal', + ' ---', + ' message: \'Some diagnostic message\'', + ' data:', + ' perf: 12.345', + ' unit: seconds', + ' ...', + 'ok 2 should be equivalent', + '', + '1..2', + '# tests 2', + '# pass 2', + '', + '# ok', + '', + '' +].join('\n'); + +var code = [ + 'var test = require(\'../\');', + '', + 'test(\'beep\', function(t){', + ' t.plan(2);', + ' t.ok(true, \'should be equal\');', + ' t.diag({', + ' message: \'Some diagnostic message\',', + ' data: {', + ' perf: 12.345,', + ' unit: \'seconds\'', + ' }', + ' });', + ' t.ok(true, \'should be equivalent\');', + '});' +].join('\n'); + +fs.writeFileSync('diag-fixture.js', code, 'utf8'); + +tape('diag() method', function(t){ + t.plan(1); + cp.exec('node ./diag-fixture.js', function(err, stdout, stderr) { + t.equal(stdout, expected, 'Correct TAP output'); + fs.unlinkSync('diag-fixture.js'); + }); +}); diff --git a/test/double_end.js b/test/double_end.js index c405d45e..01f68512 100644 --- a/test/double_end.js +++ b/test/double_end.js @@ -15,7 +15,7 @@ test(function (t) { 'ok 1 should be equal', 'not ok 2 .end() called twice', ' ---', - ' operator: fail', + ' operator: fail', ' ...', '', '1..2', diff --git a/test/undef.js b/test/undef.js index e856a54b..8d6e0273 100644 --- a/test/undef.js +++ b/test/undef.js @@ -13,9 +13,9 @@ tap.test('array test', function (tt) { + '# undef\n' + 'not ok 1 should be equivalent\n' + ' ---\n' - + ' operator: deepEqual\n' - + ' expected: { beep: undefined }\n' - + ' actual: {}\n' + + ' operator: deepEqual\n' + + ' expected: { beep: undefined }\n' + + ' actual: {}\n' + ' ...\n' + '\n' + '1..1\n'