From bf41c63cd7be6134680f4e363cece5e64d92a40c Mon Sep 17 00:00:00 2001 From: Jay Sherby Date: Sat, 3 Mar 2018 01:16:58 -0600 Subject: [PATCH] Add calledOnceWith and calledOnceWithExactly --- README.md | 129 +++++----------------- lib/sinon-chai.js | 2 + test/callArguments.js | 246 +++++++++++++++++++++++++++++++++++++++++- test/messages.js | 41 +++++++ 4 files changed, 314 insertions(+), 104 deletions(-) diff --git a/README.md b/README.md index 61ecd45..a4602cf 100644 --- a/README.md +++ b/README.md @@ -28,108 +28,33 @@ expect(mySpy).to.have.been.calledWith("foo"); All of your favorite Sinon.JS assertions made their way into Sinon–Chai. We show the `should` syntax here; the `expect` equivalent is also available. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Sinon.JS property/methodSinon–Chai assertion
calledspy.should.have.been.called
callCountspy.should.have.callCount(n)
calledOncespy.should.have.been.calledOnce
calledTwicespy.should.have.been.calledTwice
calledThricespy.should.have.been.calledThrice
calledBeforespy1.should.have.been.calledBefore(spy2)
calledAfterspy1.should.have.been.calledAfter(spy2)
calledImmediatelyBeforespy.should.have.been.calledImmediatelyBefore(spy2)
calledImmediatelyAfterspy.should.have.been.calledImmediatelyAfter(spy2)
calledWithNewspy.should.have.been.calledWithNew
alwaysCalledWithNewspy.should.always.have.been.calledWithNew
calledOnspy.should.have.been.calledOn(context)
alwaysCalledOnspy.should.always.have.been.calledOn(context)
calledWithspy.should.have.been.calledWith(...args)
alwaysCalledWithspy.should.always.have.been.calledWith(...args)
calledWithExactlyspy.should.have.been.calledWithExactly(...args)
alwaysCalledWithExactlyspy.should.always.have.been.calledWithExactly(...args)
calledWithMatchspy.should.have.been.calledWithMatch(...args)
alwaysCalledWithMatchspy.should.always.have.been.calledWithMatch(...args)
returnedspy.should.have.returned(returnVal)
alwaysReturnedspy.should.have.always.returned(returnVal)
threwspy.should.have.thrown(errorObjOrErrorTypeStringOrNothing)
alwaysThrewspy.should.have.always.thrown(errorObjOrErrorTypeStringOrNothing)
+| Sinon.JS property/method | Sinon–Chai assertion | +|--------------------------|-------------------------------------------------------------------| +| called | spy.should.have.been.called | +| callCount | spy.should.have.callCount(n) | +| calledOnce | spy.should.have.been.calledOnce | +| calledTwice | spy.should.have.been.calledTwice | +| calledThrice | spy.should.have.been.calledThrice | +| calledBefore | spy1.should.have.been.calledBefore(spy2) | +| calledAfter | spy1.should.have.been.calledAfter(spy2) | +| calledImmediatelyBefore | spy.should.have.been.calledImmediatelyBefore(spy2) | +| calledImmediatelyAfter | spy.should.have.been.calledImmediatelyAfter(spy2) | +| calledWithNew | spy.should.have.been.calledWithNew | +| alwaysCalledWithNew | spy.should.always.have.been.calledWithNew | +| calledOn | spy.should.have.been.calledOn(context) | +| alwaysCalledOn | spy.should.always.have.been.calledOn(context) | +| calledWith | spy.should.have.been.calledWith(...args) | +| alwaysCalledWith | spy.should.always.have.been.calledWith(...args) | +| calledOnceWith | spy.should.always.have.been.calledOnceWith(...args) | +| calledWithExactly | spy.should.have.been.calledWithExactly(...args) | +| alwaysCalledWithExactly | spy.should.always.have.been.calledWithExactly(...args) | +| calledOnceWithExactly | spy.should.always.have.been.calledOnceWithExactly(...args) | +| calledWithMatch | spy.should.have.been.calledWithMatch(...args) | +| alwaysCalledWithMatch | spy.should.always.have.been.calledWithMatch(...args) | +| returned | spy.should.have.returned(returnVal) | +| alwaysReturned | spy.should.have.always.returned(returnVal) | +| threw | spy.should.have.thrown(errorObjOrErrorTypeStringOrNothing) | +| alwaysThrew | spy.should.have.always.thrown(errorObjOrErrorTypeStringOrNothing) | For more information on the behavior of each assertion, see [the documentation for the corresponding spy methods][spymethods]. These of course work on not only spies, but diff --git a/lib/sinon-chai.js b/lib/sinon-chai.js index 32d4e4e..194dc3a 100644 --- a/lib/sinon-chai.js +++ b/lib/sinon-chai.js @@ -140,7 +140,9 @@ sinonMethod("calledImmediatelyAfter", "been called immediately after %1"); sinonMethod("calledOn", "been called with %1 as this", ", but it was called with %t instead"); sinonMethod("calledWith", "been called with arguments %*", "%D"); + sinonMethod("calledOnceWith", "been called exactly once with arguments %*", "%D"); sinonMethod("calledWithExactly", "been called with exact arguments %*", "%D"); + sinonMethod("calledOnceWithExactly", "been called exactly once with exact arguments %*", "%D"); sinonMethod("calledWithMatch", "been called with arguments matching %*", "%D"); sinonMethod("returned", "returned %1"); exceptionalSinonMethod("thrown", "threw", "thrown %1"); diff --git a/test/callArguments.js b/test/callArguments.js index 42a49c4..c5bce2f 100644 --- a/test/callArguments.js +++ b/test/callArguments.js @@ -100,7 +100,6 @@ describe("Call arguments", function () { }); }); - describe("always calledWith", function () { it("should throw an assertion error when the spy is not called", function () { expect(function () { @@ -173,6 +172,136 @@ describe("Call arguments", function () { }); }); + describe("calledOnceWith", function () { + it("should throw an assertion error when the spy is not called", function () { + expect(function () { + spy.should.have.been.calledOnceWith(arg1, arg2); + }).to.throw(AssertionError); + }); + + it("should not throw when the spy is called once with the correct arguments", function () { + spy(arg1, arg2); + + expect(function () { + spy.should.have.been.calledOnceWith(arg1, arg2); + }).to.not.throw(); + }); + + it("should not throw when the spy is called once with the correct arguments and more", function () { + spy(arg1, arg2, notArg); + + expect(function () { + spy.should.have.been.calledOnceWith(arg1, arg2); + }).to.not.throw(); + }); + + it("should throw an assertion error when the spy is called more than once", function () { + spy(arg2, arg2); + spy(arg1, arg2); + + expect(function () { + spy.should.have.been.calledOnceWith(arg1, arg2); + }).to.throw(AssertionError); + }); + + it("should throw an assertion error when the spy is called once with incorrect arguments", function () { + spy(notArg, arg1); + + expect(function () { + spy.should.have.been.calledOnceWith(arg1, arg2); + }).to.throw(AssertionError); + }); + + it("should handle objects in arguments", function () { + spy(arg1, arg3); + var _arg3 = JSON.parse(JSON.stringify(arg3)); + + expect(function () { + spy.should.have.been.calledOnceWith(arg1, _arg3); + }).to.not.throw(); + }); + + it("should handle deep objects in arguments", function () { + spy(arg1, arg4); + var _arg4 = JSON.parse(JSON.stringify(arg4)); + + expect(function () { + spy.should.have.been.calledOnceWith(arg1, _arg4); + }).to.not.throw(); + }); + }); + + describe("always calledOnceWith", function () { + it("should throw an assertion error when the spy is not called", function () { + expect(function () { + spy.should.always.have.been.calledOnceWith(arg1, arg2); + }).to.throw(AssertionError); + expect(function () { + spy.should.have.always.been.calledOnceWith(arg1, arg2); + }).to.throw(AssertionError); + expect(function () { + spy.should.have.been.always.calledOnceWith(arg1, arg2); + }).to.throw(AssertionError); + }); + + it("should not throw when the spy is called once with the correct arguments", function () { + spy(arg1, arg2); + + expect(function () { + spy.should.always.have.been.calledOnceWith(arg1, arg2); + }).to.not.throw; + expect(function () { + spy.should.have.always.been.calledOnceWith(arg1, arg2); + }).to.not.throw; + expect(function () { + spy.should.have.been.always.calledOnceWith(arg1, arg2); + }).to.not.throw; + }); + + it("should throw an assertion error when the spy is called more than once", function () { + spy(arg1, arg2); + spy(arg1, arg2); + + expect(function () { + spy.should.always.have.been.calledOnceWith(arg1, arg2); + }).to.throw(AssertionError); + expect(function () { + spy.should.have.always.been.calledOnceWith(arg1, arg2); + }).to.throw(AssertionError); + expect(function () { + spy.should.have.been.always.calledOnceWith(arg1, arg2); + }).to.throw(AssertionError); + }); + + it("should not throw when the spy is called once with the correct arguments and more", function () { + spy(arg1, arg2, notArg); + + expect(function () { + spy.should.always.have.been.calledOnceWith(arg1, arg2); + }).to.not.throw(); + expect(function () { + spy.should.have.always.been.calledOnceWith(arg1, arg2); + }).to.not.throw(); + expect(function () { + spy.should.have.been.always.calledOnceWith(arg1, arg2); + }).to.not.throw(); + }); + + it("should throw an assertion error when the spy is called with incorrect arguments", function () { + spy(notArg, arg1); + + expect(function () { + spy.should.always.have.been.calledOnceWith(arg1, arg2); + }).to.throw(AssertionError); + expect(function () { + spy.should.have.always.been.calledOnceWith(arg1, arg2); + }).to.throw(AssertionError); + expect(function () { + spy.should.have.been.always.calledOnceWith(arg1, arg2); + }).to.throw(AssertionError); + }); + }); + describe("calledWithExactly", function () { it("should throw an assertion error when the spy is not called", function () { expect(function () { @@ -299,6 +428,120 @@ describe("Call arguments", function () { }); }); + describe("calledOnceWithExactly", function () { + it("should throw an assertion error when the spy is not called", function () { + expect(function () { + spy.should.have.been.calledOnceWithExactly(arg1, arg2); + }).to.throw(AssertionError); + }); + + it("should not throw when the spy is called once with the correct arguments", function () { + spy(arg1, arg2); + + expect(function () { + spy.should.have.been.calledOnceWithExactly(arg1, arg2); + }).to.not.throw(); + }); + + it("should throw an assertion error when the spy is called more than once", function () { + spy(arg1, arg2); + spy(arg1, arg2); + + expect(function () { + spy.should.have.been.calledOnceWithExactly(arg1, arg2); + }).to.throw(AssertionError); + }); + + it("should throw an assertion error when the spy is called once with the correct arguments and more", + function () { + spy(arg1, arg2, notArg); + + expect(function () { + spy.should.have.been.calledOnceWithExactly(arg1, arg2); + }).to.throw(AssertionError); + }); + + it("should throw an assertion error when the spy is called once with incorrect arguments", function () { + spy(notArg, arg1); + + expect(function () { + spy.should.have.been.calledOnceWithExactly(arg1, arg2); + }).to.throw(AssertionError); + }); + }); + + describe("always calledOnceWithExactly", function () { + it("should throw an assertion error when the spy is not called", function () { + expect(function () { + spy.should.always.have.been.calledOnceWithExactly(arg1, arg2); + }).to.throw(AssertionError); + expect(function () { + spy.should.have.always.been.calledOnceWithExactly(arg1, arg2); + }).to.throw(AssertionError); + expect(function () { + spy.should.have.been.always.calledOnceWithExactly(arg1, arg2); + }).to.throw(AssertionError); + }); + + it("should not throw when the spy is called once with the correct arguments", function () { + spy(arg1, arg2); + + expect(function () { + spy.should.always.have.been.calledOnceWithExactly(arg1, arg2); + }).to.not.throw(); + expect(function () { + spy.should.have.always.been.calledOnceWithExactly(arg1, arg2); + }).to.not.throw(); + expect(function () { + spy.should.have.been.always.calledOnceWithExactly(arg1, arg2); + }).to.not.throw(); + }); + + it("should throw an assertion error when the spy is called more than once", function () { + spy(arg1, arg2); + spy(arg1, arg2); + + expect(function () { + spy.should.always.have.been.calledOnceWithExactly(arg1, arg2); + }).to.throw(AssertionError); + expect(function () { + spy.should.have.always.been.calledOnceWithExactly(arg1, arg2); + }).to.throw(AssertionError); + expect(function () { + spy.should.have.been.always.calledOnceWithExactly(arg1, arg2); + }).to.throw(AssertionError); + }); + + it("should throw an assertion error when the spy is called once with the correct arguments and more", + function () { + spy(arg1, arg2, notArg); + + expect(function () { + spy.should.always.have.been.calledOnceWithExactly(arg1, arg2); + }).to.throw(AssertionError); + expect(function () { + spy.should.have.always.been.calledOnceWithExactly(arg1, arg2); + }).to.throw(AssertionError); + expect(function () { + spy.should.have.been.always.calledOnceWithExactly(arg1, arg2); + }).to.throw(AssertionError); + }); + + it("should throw an assertion error when the spy is called once with incorrect arguments", function () { + spy(notArg, arg1); + + expect(function () { + spy.should.always.have.been.calledOnceWithExactly(arg1, arg2); + }).to.throw(AssertionError); + expect(function () { + spy.should.have.always.been.calledOnceWithExactly(arg1, arg2); + }).to.throw(AssertionError); + expect(function () { + spy.should.have.been.always.calledOnceWithExactly(arg1, arg2); + }).to.throw(AssertionError); + }); + }); + describe("calledWithMatch", function () { it("should throw an assertion error when the spy is not called", function () { expect(function () { @@ -352,7 +595,6 @@ describe("Call arguments", function () { }); }); - describe("always calledWithMatch", function () { it("should throw an assertion error when the spy is not called", function () { expect(function () { diff --git a/test/messages.js b/test/messages.js index fe91662..a233462 100644 --- a/test/messages.js +++ b/test/messages.js @@ -28,6 +28,13 @@ describe("Messages", function () { expect(function () { spy.should.have.callCount(4); }).to.throw("expected spy to have been called exactly 4 times, but it was called 0 times"); + + expect(function () { + spy.should.have.been.calledOnceWith(); + }).to.throw("expected spy to have been called exactly once with arguments"); + expect(function () { + spy.should.have.been.calledOnceWithExactly(); + }).to.throw("expected spy to have been called exactly once with exact arguments"); }); it("should be correct for the negated cases", function () { @@ -241,6 +248,12 @@ describe("Messages", function () { expect(function () { spy.should.have.been.calledWithMatch(sinon.match("foo")); }).to.throw("expected spy to have been called with arguments matching match(\"foo\")"); + expect(function () { + spy.should.have.been.calledOnceWith("a", "b", "c"); + }).to.throw("expected spy to have been called exactly once with arguments a, b, c"); + expect(function () { + spy.should.have.been.calledOnceWithExactly("a", "b", "c"); + }).to.throw("expected spy to have been called exactly once with exact arguments a, b, c"); expect(function () { spy.getCall(0).should.have.been.calledWith("a", "b", "c"); @@ -267,6 +280,12 @@ describe("Messages", function () { expect(function () { spy.should.not.have.been.calledWithMatch(sinon.match(1)); }).to.throw("expected spy to not have been called with arguments matching match(1)"); + expect(function () { + spy.should.not.have.been.calledOnceWith(1, 2, 3); + }).to.throw("expected spy to not have been called exactly once with arguments 1, 2, 3"); + expect(function () { + spy.should.not.have.been.calledOnceWithExactly(1, 2, 3); + }).to.throw("expected spy to not have been called exactly once with exact arguments 1, 2, 3"); expect(function () { spy.getCall(0).should.not.have.been.calledWith(1, 2, 3); @@ -299,6 +318,28 @@ describe("Messages", function () { expect(function () { spy.should.always.have.been.calledWithMatch(sinon.match(1)); }).to.throw(expectedMatch); + + var expectedOnce = /expected spy to have been called exactly once with arguments 1, 2, 3/; + expect(function () { + spy.should.always.have.been.calledOnceWith(1, 2, 3); + }).to.throw(expectedOnce); + + var expectedExactlyOnce = /expected spy to have been called exactly once with exact arguments 1, 2, 3/; + expect(function () { + spy.should.always.have.been.calledOnceWithExactly(1, 2, 3); + }).to.throw(expectedExactlyOnce); + + spy.resetHistory(); + spy(1, 2, 3); + spy(1, 2, 3); + + expect(function () { + spy.should.always.have.been.calledOnceWith(1, 2, 3); + }).to.throw(expectedOnce); + + expect(function () { + spy.should.always.have.been.calledOnceWithExactly(1, 2, 3); + }).to.throw(expectedExactlyOnce); }); });