From cbd61238734793ffbb6e7497da9143b1d7b90d1d Mon Sep 17 00:00:00 2001 From: Reid Burke Date: Thu, 17 May 2012 14:48:55 -0700 Subject: [PATCH] Add Mocha-style multi-line string diffs. Instead of using eyes for strings, use diff to present a colored diff of the expected vs. actual results. --- lib/assert/error.js | 93 ++++++++++++++++++++++++++++++++++++++++++--- package.json | 48 ++++++++++++++++------- 2 files changed, 123 insertions(+), 18 deletions(-) diff --git a/lib/assert/error.js b/lib/assert/error.js index 3f52271..e864e7c 100644 --- a/lib/assert/error.js +++ b/lib/assert/error.js @@ -1,5 +1,52 @@ var stylize = require('../vows/console').stylize; var inspect = require('../vows/console').inspect; +var diff = require('diff'); + +/** + * Pad the given `str` to `len`. + * + * @param {String} str + * @param {String} len + * @return {String} + * @api private + */ + +function pad(str, len) { + str = String(str); + return Array(len - str.length + 1).join(' ') + str; +} + +/** + * Color lines for `str`, using the color `name`. + * + * @param {String} name + * @param {String} str + * @return {String} + * @api private + */ + +function styleLines(str, name) { + return str.split('\n').map(function(str){ + return stylize(str, name); + }).join('\n'); +} + +/** + * Return a character diff for `err`. + * + * @param {Error} err + * @return {String} + * @api private + */ + +function errorDiff(err, type) { + return diff['diff' + type](err.actual, err.expected).map(function(str){ + if (/^(\n+)$/.test(str.value)) str.value = Array(++RegExp.$1.length).join(''); + if (str.added) return styleLines(str.value, 'green'); + if (str.removed) return styleLines(str.value, 'red'); + return str.value; + }).join(''); +} require('assert').AssertionError.prototype.toString = function () { var that = this, @@ -10,14 +57,50 @@ require('assert').AssertionError.prototype.toString = function () { } function parse(str) { - var actual = inspect(that.actual, {showHidden: that.actual instanceof Error}), - expected; + var actual = that.actual, + expected = that.expected, + msg, len; + + if ( + 'string' === typeof actual && + 'string' === typeof expected + ) { + len = Math.max(actual.length, expected.length); + + if (len < 20) msg = errorDiff(that, 'Chars'); + else msg = errorDiff(that, 'Words'); + + // linenos + var lines = msg.split('\n'); + if (lines.length > 4) { + var width = String(lines.length).length; + msg = lines.map(function(str, i){ + return pad(++i, width) + ' |' + ' ' + str; + }).join('\n'); + } + + // legend + msg = '\n' + + stylize('actual', 'green') + + ' ' + + stylize('expected', 'red') + + '\n\n' + + msg + + '\n'; + + // indent + msg = msg.replace(/^/gm, ' '); + + return msg; + } + + actual = inspect(actual, {showHidden: actual instanceof Error}); - if (that.expected instanceof Function) { - expected = that.expected.name; + if (expected instanceof Function) { + expected = expected.name; } else { - expected = inspect(that.expected, {showHidden: that.actual instanceof Error}); + expected = inspect(expected, {showHidden: actual instanceof Error}); } return str.replace(/{actual}/g, actual). diff --git a/package.json b/package.json index 388f795..9fb04a8 100644 --- a/package.json +++ b/package.json @@ -1,15 +1,37 @@ { - "name" : "vows", - "description" : "Asynchronous BDD & continuous integration for node.js", - "url" : "http://vowsjs.org", - "keywords" : ["testing", "spec", "test", "BDD"], - "author" : "Alexis Sellier ", - "contributors" : [{ "name": "Charlie Robbins", "email": "charlie.robbins@gmail.com" }], - "dependencies" : {"eyes": ">=0.1.6"}, - "main" : "./lib/vows", - "bin" : { "vows": "./bin/vows" }, - "directories" : { "test": "./test", "bin": "./bin" }, - "version" : "0.6.2", - "scripts" : {"test": "./bin/vows --spec"}, - "engines" : {"node": ">=0.2.6"} + "name": "vows", + "description": "Asynchronous BDD & continuous integration for node.js", + "url": "http://vowsjs.org", + "keywords": [ + "testing", + "spec", + "test", + "BDD" + ], + "author": "Alexis Sellier ", + "contributors": [ + { + "name": "Charlie Robbins", + "email": "charlie.robbins@gmail.com" + } + ], + "dependencies": { + "eyes": ">=0.1.6", + "diff": "~1.0.3" + }, + "main": "./lib/vows", + "bin": { + "vows": "./bin/vows" + }, + "directories": { + "test": "./test", + "bin": "./bin" + }, + "version": "0.6.2", + "scripts": { + "test": "./bin/vows --spec" + }, + "engines": { + "node": ">=0.2.6" + } }