From e5e6835bcd0e9a6839073cb3764685dd1ec939eb Mon Sep 17 00:00:00 2001 From: Mike Eve Date: Thu, 15 Mar 2018 07:33:08 +0000 Subject: [PATCH] Return returned value of invokant when using yields* and callsArg* (#1724) --- lib/sinon/behavior.js | 11 +- test/stub-test.js | 257 ++++++++++++++++++++++++++++++++++++------ 2 files changed, 233 insertions(+), 35 deletions(-) diff --git a/lib/sinon/behavior.js b/lib/sinon/behavior.js index 3684dd9a7..03faba8a6 100644 --- a/lib/sinon/behavior.js +++ b/lib/sinon/behavior.js @@ -92,9 +92,11 @@ function callCallback(behavior, args) { func.apply(behavior.callbackContext, behavior.callbackArguments); }); } else { - func.apply(behavior.callbackContext, behavior.callbackArguments); + return func.apply(behavior.callbackContext, behavior.callbackArguments); } } + + return undefined; } var proto = { @@ -125,7 +127,7 @@ var proto = { }, invoke: function invoke(context, args) { - callCallback(this, args); + var returnValue = callCallback(this, args); if (this.exception) { throw this.exception; @@ -156,7 +158,12 @@ var proto = { return (this.promiseLibrary || Promise).reject(this.returnValue); } else if (this.callsThrough) { return this.stub.wrappedMethod.apply(context, args); + } else if (typeof this.returnValue !== "undefined") { + return this.returnValue; + } else if (typeof this.callArgAt === "number") { + return returnValue; } + return this.returnValue; }, diff --git a/test/stub-test.js b/test/stub-test.js index 5b8e8628b..e27bf8c88 100644 --- a/test/stub-test.js +++ b/test/stub-test.js @@ -712,6 +712,14 @@ describe("stub", function () { stub.callsArg({}); }, "TypeError"); }); + + it("returns result of invocant", function () { + var stub = this.stub.callsArg(0); + var callback = createStub().returns("return value"); + + assert.same(stub(callback), "return value"); + assert(callback.calledOnce); + }); }); describe(".callsArgWith", function () { @@ -770,6 +778,14 @@ describe("stub", function () { stub.callsArgWith({}); }, "TypeError"); }); + + it("returns result of invocant", function () { + var stub = this.stub.callsArgWith(0, "test"); + var callback = createStub().returns("return value"); + + assert.same(stub(callback), "return value"); + assert(callback.calledOnce); + }); }); describe(".callsArgOn", function () { @@ -839,6 +855,15 @@ describe("stub", function () { stub.callsArgOn(this.fakeContext, 2); }, "TypeError"); }); + + it("returns result of invocant", function () { + var stub = this.stub.callsArgOn(0, this.fakeContext); + var callback = createStub().returns("return value"); + + assert.same(stub(callback), "return value"); + assert(callback.calledOnce); + assert(callback.calledOn(this.fakeContext)); + }); }); describe(".callsArgOnWith", function () { @@ -945,6 +970,16 @@ describe("stub", function () { stub.callsArgOnWith({}); }, "TypeError"); }); + + it("returns result of invocant", function () { + var object = {}; + var stub = this.stub.callsArgOnWith(0, this.fakeContext, object); + var callback = createStub().returns("return value"); + + assert.same(stub(callback), "return value"); + assert(callback.calledOnce); + assert(callback.calledWith(object)); + }); }); describe(".callsFake", function () { @@ -1269,36 +1304,48 @@ describe("stub", function () { }); }); - it("plays nice with throws", function () { + it("throws takes precedent over yielded return value", function () { var stub = createStub().throws().yields(); - var spy = createSpy(); + var callback = createStub().returns("return value"); + assert.exception(function () { - stub(spy); + stub(callback); }); - assert(spy.calledOnce); + assert(callback.calledOnce); }); - it("plays nice with returns", function () { + it("returns takes precedent over yielded return value", function () { var obj = {}; var stub = createStub().returns(obj).yields(); - var spy = createSpy(); - assert.same(stub(spy), obj); - assert(spy.calledOnce); + var callback = createStub().returns("return value"); + + assert.same(stub(callback), obj); + assert(callback.calledOnce); }); - it("plays nice with returnsArg", function () { + it("returnsArg takes precedent over yielded return value", function () { var stub = createStub().returnsArg(0).yields(); - var spy = createSpy(); - assert.same(stub(spy), spy); - assert(spy.calledOnce); + var callback = createStub().returns("return value"); + + assert.same(stub(callback), callback); + assert(callback.calledOnce); }); - it("plays nice with returnsThis", function () { + it("returnsThis takes precedent over yielded return value", function () { var obj = {}; var stub = createStub().returnsThis().yields(); - var spy = createSpy(); - assert.same(stub.call(obj, spy), obj); - assert(spy.calledOnce); + var callback = createStub().returns("return value"); + + assert.same(stub.call(obj, callback), obj); + assert(callback.calledOnce); + }); + + it("returns the result of the yielded callback", function () { + var stub = createStub().yields(); + var callback = createStub().returns("return value"); + + assert.same(stub(callback), "return value"); + assert(callback.calledOnce); }); }); @@ -1373,36 +1420,48 @@ describe("stub", function () { }); }); - it("plays nice with throws", function () { - var stub = createStub().throws().yieldsRight(); - var spy = createSpy(); + it("throws takes precedent over yielded return value", function () { + var stub = createStub().yieldsRight().throws(); + var callback = createStub().returns("return value"); + assert.exception(function () { - stub(spy); + stub(callback); }); - assert(spy.calledOnce); + assert(callback.calledOnce); }); - it("plays nice with returns", function () { + it("returns takes precedent over yielded return value", function () { var obj = {}; var stub = createStub().returns(obj).yieldsRight(); - var spy = createSpy(); - assert.same(stub(spy), obj); - assert(spy.calledOnce); + var callback = createStub().returns("return value"); + + assert.same(stub(callback), obj); + assert(callback.calledOnce); }); - it("plays nice with returnsArg", function () { + it("returnsArg takes precedent over yielded return value", function () { var stub = createStub().returnsArg(0).yieldsRight(); - var spy = createSpy(); - assert.same(stub(spy), spy); - assert(spy.calledOnce); + var callback = createStub().returns("return value"); + + assert.same(stub(callback), callback); + assert(callback.calledOnce); }); - it("plays nice with returnsThis", function () { + it("returnsThis takes precedent over yielded return value", function () { var obj = {}; var stub = createStub().returnsThis().yieldsRight(); - var spy = createSpy(); - assert.same(stub.call(obj, spy), obj); - assert(spy.calledOnce); + var callback = createStub().returns("return value"); + + assert.same(stub.call(obj, callback), obj); + assert(callback.calledOnce); + }); + + it("returns the result of the yielded callback", function () { + var stub = createStub().yields(); + var callback = createStub().returns("return value"); + + assert.same(stub(callback), "return value"); + assert(callback.calledOnce); }); }); @@ -1496,6 +1555,50 @@ describe("stub", function () { this.stub(callback); }); }); + + it("throws takes precedent over yielded return value", function () { + var stub = this.stub.throws().yieldsOn(this.fakeContext); + var callback = createStub().returns("return value"); + + assert.exception(function () { + stub(callback); + }); + assert(callback.calledOnce); + }); + + it("returns takes precedent over yielded return value", function () { + var obj = {}; + var stub = this.stub.returns(obj).yieldsOn(this.fakeContext); + var callback = createStub().returns("return value"); + + assert.same(stub(callback), obj); + assert(callback.calledOnce); + }); + + it("returnsArg takes precedent over yielded return value", function () { + var stub = this.stub.returnsArg(0).yieldsOn(); + var callback = createStub().returns("return value"); + + assert.same(stub(callback), callback); + assert(callback.calledOnce); + }); + + it("returnsThis takes precedent over yielded return value", function () { + var obj = {}; + var stub = this.stub.returnsThis().yieldsOn(this.fakeContext); + var callback = createStub().returns("return value"); + + assert.same(stub.call(obj, callback), obj); + assert(callback.calledOnce); + }); + + it("returns the result of the yielded callback", function () { + var stub = this.stub.yieldsOn(this.fakeContext); + var callback = createStub().returns("return value"); + + assert.same(stub(callback), "return value"); + assert(callback.calledOnce); + }); }); describe(".yieldsTo", function () { @@ -1584,6 +1687,50 @@ describe("stub", function () { stub({ error: callback }); }); }); + + it("throws takes precedent over yielded return value", function () { + var stub = createStub().throws().yieldsTo("success"); + var callback = createStub().returns("return value"); + + assert.exception(function () { + stub({success: callback}); + }); + assert(callback.calledOnce); + }); + + it("returns takes precedent over yielded return value", function () { + var obj = {}; + var stub = createStub().returns(obj).yieldsTo("success"); + var callback = createStub().returns("return value"); + + assert.same(stub({success: callback}), obj); + assert(callback.calledOnce); + }); + + it("returnsArg takes precedent over yielded return value", function () { + var stub = createStub().returnsArg(0).yieldsTo("success"); + var callback = createStub().returns("return value"); + + assert.equals(stub({success: callback}), {success: callback}); + assert(callback.calledOnce); + }); + + it("returnsThis takes precedent over yielded return value", function () { + var obj = {}; + var stub = createStub().returnsThis().yieldsTo("success"); + var callback = createStub().returns("return value"); + + assert.same(stub.call(obj, {success: callback}), obj); + assert(callback.calledOnce); + }); + + it("returns the result of the yielded callback", function () { + var stub = createStub().yieldsTo("success"); + var callback = createStub().returns("return value"); + + assert.same(stub({success: callback}), "return value"); + assert(callback.calledOnce); + }); }); describe(".yieldsToOn", function () { @@ -1694,6 +1841,50 @@ describe("stub", function () { this.stub({ error: callback }); }); }); + + it("throws takes precedent over yielded return value", function () { + var stub = this.stub.throws().yieldsToOn("success", this.fakeContext); + var callback = createStub().returns("return value"); + + assert.exception(function () { + stub({success: callback}); + }); + assert(callback.calledOnce); + }); + + it("returns takes precedent over yielded return value", function () { + var obj = {}; + var stub = this.stub.returns(obj).yieldsToOn("success", this.fakeContext); + var callback = createStub().returns("return value"); + + assert.same(stub({success: callback}), obj); + assert(callback.calledOnce); + }); + + it("returnsArg takes precedent over yielded return value", function () { + var stub = this.stub.returnsArg(0).yieldsToOn("success", this.fakeContext); + var callback = createStub().returns("return value"); + + assert.equals(stub({success: callback}), {success: callback}); + assert(callback.calledOnce); + }); + + it("returnsThis takes precedent over yielded return value", function () { + var obj = {}; + var stub = this.stub.returnsThis().yieldsToOn("success", this.fakeContext); + var callback = createStub().returns("return value"); + + assert.same(stub.call(obj, {success: callback}), obj); + assert(callback.calledOnce); + }); + + it("returns the result of the yielded callback", function () { + var stub = this.stub.yieldsToOn("success", this.fakeContext); + var callback = createStub().returns("return value"); + + assert.same(stub({success: callback}), "return value"); + assert(callback.calledOnce); + }); }); describe(".withArgs", function () {