Skip to content

Commit

Permalink
Make suggestions when using an unknown assertion
Browse files Browse the repository at this point in the history
  • Loading branch information
sunesimonsen committed Jun 30, 2013
1 parent 746c790 commit a40553a
Showing 1 changed file with 64 additions and 3 deletions.
67 changes: 64 additions & 3 deletions lib/unexpected.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,13 @@ var root = this;
var handler = assertionRule.handler;
handler.apply(assertion, args);
} else {
throw new Error('Unknown assertion "' + testDescriptionString + '"');
var message =
'Unknown assertion "' + testDescriptionString + '", ' +
'did you mean:\n';

var similarAssertions = expect.findAssertionSimilarTo(testDescriptionString);
message += similarAssertions.join('\n');
throw new Error(message);
}
}

Expand Down Expand Up @@ -170,6 +176,61 @@ var root = this;
});
};

/**
* Levenshtein distance algorithm from wikipedia
* http://en.wikibooks.org/wiki/Algorithm_Implementation/Strings/Levenshtein_distance#JavaScript
*/
function levenshteinDistance(a, b){
if (a.length === 0) return b.length;
if (b.length === 0) return a.length;

var matrix = [];

// increment along the first column of each row
var i;
for(i = 0; i <= b.length; i++){
matrix[i] = [i];
}

// increment each column in the first row
var j;
for(j = 0; j <= a.length; j++){
matrix[0][j] = j;
}

// Fill in the rest of the matrix
for(i = 1; i <= b.length; i++){
for(j = 1; j <= a.length; j++){
if(b.charAt(i-1) == a.charAt(j-1)){
matrix[i][j] = matrix[i-1][j-1];
} else {
matrix[i][j] = Math.min(matrix[i-1][j-1] + 1, // substitution
Math.min(matrix[i][j-1] + 1, // insertion
matrix[i-1][j] + 1)); // deletion
}
}
}

return matrix[b.length][a.length];
}

expect.findAssertionSimilarTo = function (text) {
var editDistrances = [];
forEach(getKeys(assertions), function (assertion) {
var distance = levenshteinDistance(text, assertion);
editDistrances.push({
assertion: assertion,
distance: distance
});
});
editDistrances.sort(function (x, y) {
return x.distance - y.distance;
});
return map(editDistrances.slice(0, 5), function (editDistrance) {
return editDistrance.assertion;
});
};

expect.addAssertion('to [not] be', function (value) {
this.assert(this.obj === value);
});
Expand Down Expand Up @@ -356,7 +417,7 @@ var root = this;
expect.eql = eql;

///////////////////////// Helper functions ///////////////////////////////

function bind(fn, scope) {
return function () {
return fn.apply(scope, arguments);
Expand Down Expand Up @@ -1148,7 +1209,7 @@ var root = this;
return JSON;
})();
//////////////////////////////////////////////////////////////////////////

// Support three module loading scenarios
if (typeof require === 'function' && typeof exports === 'object' && typeof module === 'object') {
// CommonJS/Node.js
Expand Down

0 comments on commit a40553a

Please sign in to comment.