Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 3 additions & 7 deletions lib/assertThat.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,9 @@ function assertThat(reason, actual, matcher) {
matcher.describeMismatch(actual, description);

var errorProperties = {};
if (_.isFunction(matcher.getExpectedForDiff) &&
_.isFunction(matcher.formatActualForDiff)) {
errorProperties = {
showDiff: true,
expected: matcher.getExpectedForDiff(),
actual: matcher.formatActualForDiff(actual)
};
if (_.isFunction(matcher.getDiffItems)) {
errorProperties = matcher.getDiffItems(actual);
errorProperties.showDiff = true;
}

throw new AssertionError(description.get(), errorProperties, assertThat);
Expand Down
3 changes: 1 addition & 2 deletions lib/matchers/Is.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ var Is = acceptingMatcher(function Is(innerMatcher) {
describeMismatch: function (value, description) {
return innerMatcher.describeMismatch(value, description);
},
getExpectedForDiff: innerMatcher.getExpectedForDiff,
formatActualForDiff: innerMatcher.formatActualForDiff
getDiffItems: innerMatcher.getDiffItems
});
});

Expand Down
8 changes: 6 additions & 2 deletions lib/matchers/IsEqual.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,12 @@ function IsEqual(expectedValue) {
describeTo: function (description) {
description.appendValue(expectedValue);
},
getExpectedForDiff: function () { return expectedValue; },
formatActualForDiff: function (actual) { return actual; }
getDiffItems: function (actual) {
return {
expected: expectedValue,
actual: actual
};
}
});
}

Expand Down
28 changes: 28 additions & 0 deletions lib/matchers/IsObjectWithProperties.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ var _ = require('lodash')
, asMatcher = require('./IsEqual').asMatcher
, defined = require('./IsDefined').defined
;
var Description = require('../Description');
var promiseAgnostic = require('./promiseAgnostic');

function IsObjectWithProperties(properties) {
Expand Down Expand Up @@ -56,6 +57,33 @@ function IsObjectWithProperties(properties) {
.append(' ');
return propertyMatchers[key].describeMismatch(actual[key], description);
});
},

getDiffItems: function (actual) {
var relevantMatchers = _.pick(propertyMatchers, function (matcher, key) {
return !matcher.matches(actual[key]);
});

var guessDiffItems = function (matcher, actual) {
var description = new Description();
matcher.describeTo(description);
return {
expected: description.get(),
actual: actual
};
};

var diffItemsIndividually = _.mapValues(relevantMatchers, function (matcher, key) {
if (_.isFunction(matcher.getDiffItems)) {
return matcher.getDiffItems(actual[key]);
}
return guessDiffItems(matcher, actual[key]);
});

return {
expected: _.mapValues(diffItemsIndividually, 'expected'),
actual: _.mapValues(diffItemsIndividually, 'actual')
};
}
});
}
Expand Down
8 changes: 6 additions & 2 deletions lib/matchers/SubstringMatcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,12 @@ function SubstringMatcher(substring, relation, matchesString) {
.append('was ')
.appendValue(actual);
},
getExpectedForDiff: function () { return substring; },
formatActualForDiff: function (actual) { return actual; }
getDiffItems: function (actual) {
return {
expected: substring,
actual: actual
};
}
});
}

Expand Down
8 changes: 4 additions & 4 deletions lib/promiseThat.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@ function promiseThat(reason, actual, matcher) {
.appendDescriptionOf(matcher)
.append('\n but: ');
return q(matcher.describeMismatch(actual, description)).then(function () {
if (!_.isFunction(matcher.getExpectedForDiff) ||
!_.isFunction(matcher.formatActualForDiff)) {
if (!_.isFunction(matcher.getDiffItems)) {
return {};
}

var diffItems = matcher.getDiffItems(actual);
return q.all([
matcher.getExpectedForDiff(),
matcher.formatActualForDiff(actual)
diffItems.expected,
diffItems.actual
]).spread(function (expected, actual) {
return {
showDiff: true,
Expand Down
10 changes: 5 additions & 5 deletions test/assertThatSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,11 @@ describe('assertThat', function () {
var thrown;

var testMatcher = new TestMatcher(function () { return false; });
testMatcher.getExpectedForDiff = function () {
return 'expected for diff';
};
testMatcher.formatActualForDiff = function (actual) {
return 'actual for diff: ' + actual;
testMatcher.getDiffItems = function (actual) {
return {
expected: 'expected for diff',
actual: 'actual for diff: ' + actual
};
};

try {
Expand Down
56 changes: 56 additions & 0 deletions test/matchers/IsObjectWithPropertiesSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ var IsObjectWithProperties = require('../../lib/matchers/IsObjectWithProperties'
, __ = require('../../lib/hamjest')
;
var deferMatcher = require('../deferMatcher');
var TestMatcher = require('../TestMatcher');

describe('IsObjectWithProperties', function () {

Expand Down Expand Up @@ -80,6 +81,61 @@ describe('IsObjectWithProperties', function () {
});
});

describe('diff', function() {
it('should exist', function () {
__.assertThat(sut.getDiffItems({}), __.hasProperties({
expected: __.defined(),
actual: __.defined()
}));
});

it('should contain mismatched properties', function () {
var diffObjects = sut.getDiffItems(new Person('Jim', 2));
__.assertThat(diffObjects, __.everyItem(__.hasProperty('name')));
});

it('should omit matched properties', function () {
var diffObjects = sut.getDiffItems({name: 'Joe', children: 0});
__.assertThat(diffObjects, __.everyItem(__.not(__.hasProperty('name'))));
});

it('should omit extra properties', function () {
var diffObjects = sut.getDiffItems({foo: 'bar'});
__.assertThat(diffObjects, __.everyItem(__.not(__.hasProperty('foo'))));
});

it('should use diff from diff-capable nested matcher', function () {
var testMatcher = new TestMatcher(function () { return false; });
testMatcher.getDiffItems = function (actual) {
return {
expected: 'expected from nested',
actual: 'actual from nested: ' + actual
};
};
var sutWithNestedMatcher = hasProperties({a: testMatcher});
var diffObjects = sutWithNestedMatcher.getDiffItems({a: 1});
__.assertThat(diffObjects, __.hasProperties({
expected: {a: 'expected from nested'},
actual: {a: 'actual from nested: 1'}
}));
});

it('should use actual and mismatch description from non-diff-capable nested matcher', function () {
var testMatcher = new TestMatcher(function () { return false; });

var description = new Description();
testMatcher.describeTo(description);

var sutWithNestedMatcher = hasProperties({a: testMatcher});
var diffObjects = sutWithNestedMatcher.getDiffItems({a: 1});

__.assertThat(diffObjects, __.hasProperties({
expected: {a: description.get()},
actual: {a: 1}
}));
});
});

describe('with a promising matcher', function () {
beforeEach(function () {
sut = hasProperties({
Expand Down
12 changes: 5 additions & 7 deletions test/matchers/SubstringMatcherSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ var AssertionError = require('assertion-error')
, __ = require('../../lib/hamjest')
, assertTrue = require('../asserts').assertTrue
, assertFalse = require('../asserts').assertFalse
, assertEquals = require('../asserts').assertEquals
;

describe('SubstringMatcher', function () {
Expand Down Expand Up @@ -41,12 +40,11 @@ describe('SubstringMatcher', function () {
assertFalse(sut.matches(5));
});

it('should provide expected for diff', function () {
assertEquals('a value', sut.getExpectedForDiff());
});

it('should format actual for diff', function() {
assertEquals('foo', sut.formatActualForDiff('foo'));
it('should provide diff items', function () {
__.assertThat(sut.getDiffItems('foo'), __.equalTo({
expected: 'a value',
actual: 'foo'
}));
});

describe('description', function () {
Expand Down
10 changes: 5 additions & 5 deletions test/promiseThatSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -160,11 +160,11 @@ describe('promiseThat', function () {

it('should pass diff representations to AssertionError', function (done) {
var testMatcher = new TestMatcher(function () { return false; });
testMatcher.getExpectedForDiff = function () {
return 'expected for diff';
};
testMatcher.formatActualForDiff = function (actual) {
return q('actual for diff: ' + actual);
testMatcher.getDiffItems = function (actual) {
return {
expected: 'expected for diff',
actual: q('actual for diff: ' + actual)
};
};

promiseThat('actual value', testMatcher).done(
Expand Down