diff --git a/lib/sinon-chai.js b/lib/sinon-chai.js index 194dc3a..ac09536 100644 --- a/lib/sinon-chai.js +++ b/lib/sinon-chai.js @@ -93,19 +93,42 @@ }); } + function isDiffSupportedMethod(sinonMethodName) { + return (sinonMethodName.indexOf("calledWith") === 0) || (sinonMethodName.indexOf("calledOnceWith") === 0); + } + function createSinonMethodHandler(sinonName, action, nonNegatedSuffix) { return function () { assertCanWorkWith(this); - var alwaysSinonMethod = "always" + sinonName[0].toUpperCase() + sinonName.substring(1); var shouldBeAlways = utils.flag(this, "always") && typeof this._obj[alwaysSinonMethod] === "function"; var sinonMethodName = shouldBeAlways ? alwaysSinonMethod : sinonName; var messages = getMessages(this._obj, action, nonNegatedSuffix, shouldBeAlways, slice.call(arguments)); + var passed = this._obj[sinonMethodName].apply(this._obj, arguments); + var actual; + var expected; + var enableDiff; + if (!passed) { + if (isDiffSupportedMethod(sinonMethodName)) { + enableDiff = true; + var lastCall = this._obj.lastCall || this._obj; + actual = lastCall.args && lastCall.args; + if (this._obj.callCount === 0) { + actual = undefined; + } + + expected = slice.call(arguments); + } + } + this.assert( - this._obj[sinonMethodName].apply(this._obj, arguments), + passed, messages.affirmative, - messages.negative + messages.negative, + expected, + actual, + enableDiff ); }; } diff --git a/test/messages.js b/test/messages.js index a233462..906bf23 100644 --- a/test/messages.js +++ b/test/messages.js @@ -472,6 +472,139 @@ describe("Messages", function () { }); }); + describe("diff support", function () { + it("should add actual/expected and set enableDiff to true", function () { + var spy = sinon.spy(); + spy("foo1"); + + var err; + + try { + expect(spy).to.have.been.calledWith("bar"); + } catch (e) { + err = e; + } + expect(err).ok; + expect(err).to.ownProperty("showDiff", true); + expect(err).to.ownProperty("actual").deep.eq(["foo1"]); + expect(err).to.ownProperty("expected").deep.eq(["bar"]); + }); + + it("should add diff when calledOnceWith matcher", function () { + var spy = sinon.spy(); + spy("foo1"); + + var err; + + try { + expect(spy).to.have.been.calledOnceWith("bar"); + } catch (e) { + err = e; + } + expect(err).ok; + expect(err).to.ownProperty("showDiff", true); + expect(err).to.ownProperty("actual").deep.eq(["foo1"]); + expect(err).to.ownProperty("expected").deep.eq(["bar"]); + }); + + it("should add diff when calledOnceWithExactly matcher", function () { + var spy = sinon.spy(); + spy("foo1"); + + var err; + + try { + expect(spy).to.have.been.calledOnceWithExactly("bar"); + } catch (e) { + err = e; + } + expect(err).ok; + expect(err).to.ownProperty("showDiff", true); + expect(err).to.ownProperty("actual").deep.eq(["foo1"]); + expect(err).to.ownProperty("expected").deep.eq(["bar"]); + }); + + it("should use lastCall args if exists", function () { + var spy = sinon.spy(); + spy("foo1"); + spy("foo2"); + + var err; + + try { + expect(spy).to.have.been.calledWith("bar"); + } catch (e) { + err = e; + } + expect(err).ok; + expect(err).to.ownProperty("showDiff", true); + expect(err).to.ownProperty("actual").deep.eq(["foo2"]); + expect(err).to.ownProperty("expected").deep.eq(["bar"]); + }); + + it("should use args if no lastCall", function () { + var spy = sinon.spy(); + spy("foo1"); + spy("foo2"); + + var err; + + try { + expect(spy.firstCall).to.have.been.calledWith("bar"); + } catch (e) { + err = e; + } + expect(err).ok; + expect(err).to.ownProperty("showDiff", true); + expect(err).to.ownProperty("actual").deep.eq(["foo1"]); + expect(err).to.ownProperty("expected").deep.eq(["bar"]); + }); + + it("should use undefined if no call", function () { + var spy = sinon.spy(); + + var err; + + try { + expect(spy).to.have.been.calledWith("bar"); + } catch (e) { + err = e; + } + expect(err).ok; + expect(err).to.ownProperty("showDiff", true); + expect(err).to.ownProperty("actual").deep.eq(undefined); + expect(err).to.ownProperty("expected").deep.eq(["bar"]); + }); + + it("should not add actual/expected and set enableDiff to true if passes", function () { + var spy = sinon.spy(); + spy("foo", "bar", "baz"); + + var err; + + try { + spy.should.calledWithExactly("foo", "bar", "baz"); + } catch (e) { + err = e; + } + expect(err).to.be.undefined; + }); + + it("should not add actual/expected and set enableDiff if not 'calledWith' matcher", function () { + var spy = sinon.spy(); + spy("foo", "bar", "baz"); + + var err; + + try { + expect(spy).to.have.been.calledTwice(); + } catch (e) { + err = e; + } + expect(err).ownProperty("showDiff").eq(false); + }); + }); + describe("when used on a non-spy/non-call", function () { function notSpy() { // Contents don't matter