From f2a35cbec4262b311f551bdaee048adc4a4f7aae Mon Sep 17 00:00:00 2001 From: Alex Bepple Date: Thu, 4 Dec 2014 20:01:29 +0100 Subject: [PATCH 01/11] support diffs: add expected to AssertionError cp. http://tjholowaychuk.tumblr.com/post/18574009869 --- lib/assertThat.js | 9 ++++++++- test/assertThatSpec.js | 19 +++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/lib/assertThat.js b/lib/assertThat.js index 4fdcf6f..3ea7e50 100644 --- a/lib/assertThat.js +++ b/lib/assertThat.js @@ -1,6 +1,7 @@ 'use strict'; var q = require('q'); +var _ = require('lodash'); var AssertionError = require('assertion-error') , Description = require('./Description') ; @@ -24,8 +25,14 @@ function assertThat(reason, actual, matcher) { .append('\nExpected: ') .appendDescriptionOf(matcher) .append('\n but: '); + + var props = {}; + if (_.has(matcher, 'getExpectedForDiff')) { + props.expected = matcher.getExpectedForDiff(); + } + matcher.describeMismatch(actual, description); - throw new AssertionError(description.get(), {}, assertThat); + throw new AssertionError(description.get(), props, assertThat); } } diff --git a/test/assertThatSpec.js b/test/assertThatSpec.js index 4352c3c..13096fd 100644 --- a/test/assertThatSpec.js +++ b/test/assertThatSpec.js @@ -59,6 +59,25 @@ describe('assertThat', function () { assertEquals(thrown.message , 'Assertion message\nExpected: Matcher description\n but: was "real value"'); }); + it('should pass diff representations to AssertionError', function () { + var thrown; + + var testMatcher = new TestMatcher(function () { return false; }); + testMatcher.getExpectedForDiff = function () { + return 'expected for diff'; + }; + + try { + assertThat('foo', testMatcher); + } + catch (e) { + console.log(e); + thrown = e; + } + + assertEquals(thrown.expected, 'expected for diff'); + }); + it('should throw if matcher returns a promise', function () { var thrown; From b857dbf7e57b9e2478bceb97234135909d948b45 Mon Sep 17 00:00:00 2001 From: Alex Bepple Date: Thu, 4 Dec 2014 20:11:36 +0100 Subject: [PATCH 02/11] support diffs: add actual to AssertionError --- lib/assertThat.js | 3 +++ test/assertThatSpec.js | 9 ++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/assertThat.js b/lib/assertThat.js index 3ea7e50..5a53ded 100644 --- a/lib/assertThat.js +++ b/lib/assertThat.js @@ -30,6 +30,9 @@ function assertThat(reason, actual, matcher) { if (_.has(matcher, 'getExpectedForDiff')) { props.expected = matcher.getExpectedForDiff(); } + if (_.has(matcher, 'formatActualForDiff')) { + props.actual = matcher.formatActualForDiff(actual); + } matcher.describeMismatch(actual, description); throw new AssertionError(description.get(), props, assertThat); diff --git a/test/assertThatSpec.js b/test/assertThatSpec.js index 13096fd..1fdb34b 100644 --- a/test/assertThatSpec.js +++ b/test/assertThatSpec.js @@ -5,6 +5,7 @@ var AssertionError = require('assertion-error') , assertThat = require('../lib/assertThat') , assertTrue = require('./asserts').assertTrue , assertEquals = require('./asserts').assertEquals + , hasProperties = require('../lib/matchers/IsObjectWithProperties').hasProperties , TestMatcher = require('./TestMatcher') ; @@ -66,6 +67,9 @@ describe('assertThat', function () { testMatcher.getExpectedForDiff = function () { return 'expected for diff'; }; + testMatcher.formatActualForDiff = function () { + return 'actual for diff'; + }; try { assertThat('foo', testMatcher); @@ -75,7 +79,10 @@ describe('assertThat', function () { thrown = e; } - assertEquals(thrown.expected, 'expected for diff'); + assertThat(thrown, hasProperties({ + expected: 'expected for diff', + actual: 'actual for diff' + })); }); it('should throw if matcher returns a promise', function () { From 9be8b169c9b75a57e6aaa12b2c56f85ac11d1c6f Mon Sep 17 00:00:00 2001 From: Alex Bepple Date: Thu, 4 Dec 2014 20:39:37 +0100 Subject: [PATCH 03/11] turn on diffs --- lib/assertThat.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/assertThat.js b/lib/assertThat.js index 5a53ded..7eff51f 100644 --- a/lib/assertThat.js +++ b/lib/assertThat.js @@ -26,7 +26,9 @@ function assertThat(reason, actual, matcher) { .appendDescriptionOf(matcher) .append('\n but: '); - var props = {}; + var props = { + showDiff: true + }; if (_.has(matcher, 'getExpectedForDiff')) { props.expected = matcher.getExpectedForDiff(); } From 5e02f3b7ac9ee1f546a6ea64f5c45fdbab036cfd Mon Sep 17 00:00:00 2001 From: Alex Bepple Date: Thu, 4 Dec 2014 20:43:18 +0100 Subject: [PATCH 04/11] SubstringMatcher: provide diffs --- lib/matchers/SubstringMatcher.js | 4 +++- test/matchers/SubstringMatcherSpec.js | 9 +++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/lib/matchers/SubstringMatcher.js b/lib/matchers/SubstringMatcher.js index 6231330..446477f 100644 --- a/lib/matchers/SubstringMatcher.js +++ b/lib/matchers/SubstringMatcher.js @@ -25,7 +25,9 @@ function SubstringMatcher(substring, relation, matchesString) { description .append('was ') .appendValue(actual); - } + }, + getExpectedForDiff: function () { return substring; }, + formatActualForDiff: function (actual) { return actual; } }); } diff --git a/test/matchers/SubstringMatcherSpec.js b/test/matchers/SubstringMatcherSpec.js index ce08268..fe3a9d7 100644 --- a/test/matchers/SubstringMatcherSpec.js +++ b/test/matchers/SubstringMatcherSpec.js @@ -6,6 +6,7 @@ var AssertionError = require('assertion-error') , __ = require('../../lib/hamjest') , assertTrue = require('../asserts').assertTrue , assertFalse = require('../asserts').assertFalse + , assertEquals = require('../asserts').assertEquals ; describe('SubstringMatcher', function () { @@ -40,6 +41,14 @@ 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')); + }); + describe('description', function () { var description; From 94a2b3f5d703639279cae9a4a23ffc95f5aeca5a Mon Sep 17 00:00:00 2001 From: Raphael Luba Date: Tue, 9 Dec 2014 21:00:57 +0100 Subject: [PATCH 05/11] Extend diff support to `equalTo` and prevent `is` from breaking it. --- lib/assertThat.js | 4 ++-- lib/matchers/Is.js | 4 +++- lib/matchers/IsEqual.js | 4 +++- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/assertThat.js b/lib/assertThat.js index 7eff51f..d0eee6c 100644 --- a/lib/assertThat.js +++ b/lib/assertThat.js @@ -29,10 +29,10 @@ function assertThat(reason, actual, matcher) { var props = { showDiff: true }; - if (_.has(matcher, 'getExpectedForDiff')) { + if (_.isFunction(matcher.getExpectedForDiff)) { props.expected = matcher.getExpectedForDiff(); } - if (_.has(matcher, 'formatActualForDiff')) { + if (_.isFunction(matcher.formatActualForDiff)) { props.actual = matcher.formatActualForDiff(actual); } diff --git a/lib/matchers/Is.js b/lib/matchers/Is.js index df19543..4abd5ae 100644 --- a/lib/matchers/Is.js +++ b/lib/matchers/Is.js @@ -17,7 +17,9 @@ var Is = acceptingMatcher(function Is(innerMatcher) { }, describeMismatch: function (value, description) { return innerMatcher.describeMismatch(value, description); - } + }, + getExpectedForDiff: innerMatcher.getExpectedForDiff, + formatActualForDiff: innerMatcher.formatActualForDiff }); }); diff --git a/lib/matchers/IsEqual.js b/lib/matchers/IsEqual.js index 59c96b5..cf08416 100644 --- a/lib/matchers/IsEqual.js +++ b/lib/matchers/IsEqual.js @@ -11,7 +11,9 @@ function IsEqual(expectedValue) { }, describeTo: function (description) { description.appendValue(expectedValue); - } + }, + getExpectedForDiff: function () { return expectedValue; }, + formatActualForDiff: function (actual) { return actual; } }); } From 9dedeaa48f2156ccb43168aae5bf0c12feb1e592 Mon Sep 17 00:00:00 2001 From: Raphael Luba Date: Tue, 9 Dec 2014 21:39:53 +0100 Subject: [PATCH 06/11] Unfortunately, it doesn't make much sense to test `assertThat` using `assertThat`. --- test/assertThatSpec.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/test/assertThatSpec.js b/test/assertThatSpec.js index 1fdb34b..c3aef5c 100644 --- a/test/assertThatSpec.js +++ b/test/assertThatSpec.js @@ -5,7 +5,6 @@ var AssertionError = require('assertion-error') , assertThat = require('../lib/assertThat') , assertTrue = require('./asserts').assertTrue , assertEquals = require('./asserts').assertEquals - , hasProperties = require('../lib/matchers/IsObjectWithProperties').hasProperties , TestMatcher = require('./TestMatcher') ; @@ -75,14 +74,11 @@ describe('assertThat', function () { assertThat('foo', testMatcher); } catch (e) { - console.log(e); thrown = e; } - assertThat(thrown, hasProperties({ - expected: 'expected for diff', - actual: 'actual for diff' - })); + assertEquals(thrown.expected, 'expected for diff'); + assertEquals(thrown.actual, 'actual for diff'); }); it('should throw if matcher returns a promise', function () { From eaf6f884905c402b2d5b2c36573083cd0c00c1d5 Mon Sep 17 00:00:00 2001 From: Raphael Luba Date: Tue, 9 Dec 2014 21:40:03 +0100 Subject: [PATCH 07/11] Update to latest mocha --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 51a42fe..1710893 100644 --- a/package.json +++ b/package.json @@ -41,10 +41,10 @@ "grunt-contrib-nodeunit": "^0.2.2", "grunt-contrib-uglify": "^0.3.3", "grunt-contrib-watch": "^0.5.3", - "grunt-mocha-test": "^0.12.1", + "grunt-mocha-test": "^0.12.4", "jshint-stylish": "^0.1.5", "load-grunt-tasks": "^0.2.1", - "mocha": "^1.21.4", + "mocha": "^2.0.1", "time-grunt": "^0.2.10" }, "dependencies": { From 30e2638d817d3684ac61de1afa10ba3efe2d9c93 Mon Sep 17 00:00:00 2001 From: Raphael Luba Date: Tue, 9 Dec 2014 21:02:10 +0100 Subject: [PATCH 08/11] Fix: "diff" code was inserted between "description" code. --- lib/assertThat.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/assertThat.js b/lib/assertThat.js index d0eee6c..f92d556 100644 --- a/lib/assertThat.js +++ b/lib/assertThat.js @@ -25,6 +25,7 @@ function assertThat(reason, actual, matcher) { .append('\nExpected: ') .appendDescriptionOf(matcher) .append('\n but: '); + matcher.describeMismatch(actual, description); var props = { showDiff: true @@ -36,7 +37,6 @@ function assertThat(reason, actual, matcher) { props.actual = matcher.formatActualForDiff(actual); } - matcher.describeMismatch(actual, description); throw new AssertionError(description.get(), props, assertThat); } } From 95afa1e12b324cad51a165f875ea40654df1db13 Mon Sep 17 00:00:00 2001 From: Raphael Luba Date: Tue, 9 Dec 2014 21:42:00 +0100 Subject: [PATCH 09/11] Extend diff test to make sure that `actual` is provided --- test/assertThatSpec.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/assertThatSpec.js b/test/assertThatSpec.js index c3aef5c..492dd18 100644 --- a/test/assertThatSpec.js +++ b/test/assertThatSpec.js @@ -66,19 +66,19 @@ describe('assertThat', function () { testMatcher.getExpectedForDiff = function () { return 'expected for diff'; }; - testMatcher.formatActualForDiff = function () { - return 'actual for diff'; + testMatcher.formatActualForDiff = function (actual) { + return 'actual for diff: ' + actual; }; try { - assertThat('foo', testMatcher); + assertThat('actual value', testMatcher); } catch (e) { thrown = e; } assertEquals(thrown.expected, 'expected for diff'); - assertEquals(thrown.actual, 'actual for diff'); + assertEquals(thrown.actual, 'actual for diff: actual value'); }); it('should throw if matcher returns a promise', function () { From da334f6ee6a6f1a336293d9b900912e62e3828a8 Mon Sep 17 00:00:00 2001 From: Raphael Luba Date: Tue, 9 Dec 2014 21:51:12 +0100 Subject: [PATCH 10/11] Implement diff support for `promiseThat` and clean up implementation in `assertThat` --- lib/assertThat.js | 18 +++++++++--------- lib/promiseThat.js | 19 ++++++++++++++++++- test/promiseThatSpec.js | 23 +++++++++++++++++++++++ 3 files changed, 50 insertions(+), 10 deletions(-) diff --git a/lib/assertThat.js b/lib/assertThat.js index f92d556..058a10e 100644 --- a/lib/assertThat.js +++ b/lib/assertThat.js @@ -27,17 +27,17 @@ function assertThat(reason, actual, matcher) { .append('\n but: '); matcher.describeMismatch(actual, description); - var props = { - showDiff: true - }; - if (_.isFunction(matcher.getExpectedForDiff)) { - props.expected = matcher.getExpectedForDiff(); - } - if (_.isFunction(matcher.formatActualForDiff)) { - props.actual = matcher.formatActualForDiff(actual); + var errorProperties = {}; + if (_.isFunction(matcher.getExpectedForDiff) && + _.isFunction(matcher.formatActualForDiff)) { + errorProperties = { + showDiff: true, + expected: matcher.getExpectedForDiff(), + actual: matcher.formatActualForDiff(actual) + }; } - throw new AssertionError(description.get(), props, assertThat); + throw new AssertionError(description.get(), errorProperties, assertThat); } } diff --git a/lib/promiseThat.js b/lib/promiseThat.js index a351e2c..a65a279 100644 --- a/lib/promiseThat.js +++ b/lib/promiseThat.js @@ -3,6 +3,7 @@ var q = require('q'); var AssertionError = require('assertion-error'); var Description = require('./Description'); +var _ = require('lodash'); function promiseThat(reason, actual, matcher) { if (arguments.length === 2) { @@ -19,7 +20,23 @@ function promiseThat(reason, actual, matcher) { .appendDescriptionOf(matcher) .append('\n but: '); return q(matcher.describeMismatch(actual, description)).then(function () { - throw new AssertionError(description.get(), {}, promiseThat); + if (!_.isFunction(matcher.getExpectedForDiff) || + !_.isFunction(matcher.formatActualForDiff)) { + return {}; + } + + return q.all([ + matcher.getExpectedForDiff(), + matcher.formatActualForDiff(actual) + ]).spread(function (expected, actual) { + return { + showDiff: true, + expected: expected, + actual: actual + }; + }); + }).then(function (errorProperties) { + throw new AssertionError(description.get(), errorProperties, promiseThat); }); } }); diff --git a/test/promiseThatSpec.js b/test/promiseThatSpec.js index 5835106..85b2ad5 100644 --- a/test/promiseThatSpec.js +++ b/test/promiseThatSpec.js @@ -157,4 +157,27 @@ describe('promiseThat', function () { deferred.resolve(); }); + + 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); + }; + + promiseThat('actual value', testMatcher).done( + function () { + fail('Should not be fulfilled'); + }, + function (reason) { + __.assertThat(reason, __.hasProperties({ + expected: 'expected for diff', + actual: 'actual for diff: actual value' + })); + done(); + } + ); + }); }); From b84a145bb9e126f79bca5f5f987dd455fb62b0c4 Mon Sep 17 00:00:00 2001 From: Alex Bepple Date: Wed, 10 Dec 2014 23:50:32 +0100 Subject: [PATCH 11/11] IsObjectWithProperties: provide naive diffs --- lib/matchers/IsObjectWithProperties.js | 6 ++++++ test/matchers/IsObjectWithPropertiesSpec.js | 10 ++++++++++ 2 files changed, 16 insertions(+) diff --git a/lib/matchers/IsObjectWithProperties.js b/lib/matchers/IsObjectWithProperties.js index 7431bb0..15735f6 100644 --- a/lib/matchers/IsObjectWithProperties.js +++ b/lib/matchers/IsObjectWithProperties.js @@ -56,6 +56,12 @@ function IsObjectWithProperties(properties) { .append(' '); return propertyMatchers[key].describeMismatch(actual[key], description); }); + }, + getExpectedForDiff: function () { + return properties; + }, + formatActualForDiff: function (actual) { + return actual; } }); } diff --git a/test/matchers/IsObjectWithPropertiesSpec.js b/test/matchers/IsObjectWithPropertiesSpec.js index 22504ec..df54d0d 100644 --- a/test/matchers/IsObjectWithPropertiesSpec.js +++ b/test/matchers/IsObjectWithPropertiesSpec.js @@ -80,6 +80,16 @@ describe('IsObjectWithProperties', function () { }); }); + it('should format actual for diff', function () { + var simple = IsObjectWithProperties.hasProperties(); + __.assertThat(simple.formatActualForDiff({a: 1}), __.equalTo({a: 1})); + }); + + it('should provide expected for diff', function () { + var simple = IsObjectWithProperties.hasProperties({a: 1}); + __.assertThat(simple.getExpectedForDiff(), __.equalTo({a: 1})); + }); + describe('with a promising matcher', function () { beforeEach(function () { sut = hasProperties({