diff --git a/lib/jasmine-core/jasmine.js b/lib/jasmine-core/jasmine.js index 2b3d9dcc..c2dfa78a 100644 --- a/lib/jasmine-core/jasmine.js +++ b/lib/jasmine-core/jasmine.js @@ -49,7 +49,7 @@ var getJasmineRequireObj = (function (jasmineGlobal) { j$.errors = jRequire.errors(); j$.Any = jRequire.Any(j$); j$.Anything = jRequire.Anything(j$); - j$.CallTracker = jRequire.CallTracker(); + j$.CallTracker = jRequire.CallTracker(j$); j$.MockDate = jRequire.MockDate(); j$.Clock = jRequire.Clock(); j$.DelayedFunctionScheduler = jRequire.DelayedFunctionScheduler(); @@ -1079,12 +1079,29 @@ getJasmineRequireObj().JsApiReporter = function() { return JsApiReporter; }; -getJasmineRequireObj().CallTracker = function() { +getJasmineRequireObj().CallTracker = function(j$) { function CallTracker() { var calls = []; + var opts = {}; + + function argCloner(context) { + var clonedArgs = []; + var argsAsArray = j$.util.argsToArray(context.args); + for(var i = 0; i < argsAsArray.length; i++) { + if(Object.prototype.toString.apply(argsAsArray[i]).match(/^\[object/)) { + clonedArgs.push(j$.util.clone(argsAsArray[i])); + } else { + clonedArgs.push(argsAsArray[i]); + } + } + context.args = clonedArgs; + } this.track = function(context) { + if(opts.cloneArgs) { + argCloner(context); + } calls.push(context); }; @@ -1125,6 +1142,11 @@ getJasmineRequireObj().CallTracker = function() { this.reset = function() { calls = []; }; + + this.saveArgumentsByValue = function() { + opts.cloneArgs = true; + }; + } return CallTracker; diff --git a/spec/core/CallTrackerSpec.js b/spec/core/CallTrackerSpec.js index ffccc538..f6f64db5 100644 --- a/spec/core/CallTrackerSpec.js +++ b/spec/core/CallTrackerSpec.js @@ -102,4 +102,19 @@ describe("CallTracker", function() { expect(callTracker.all()).toEqual([]); expect(callTracker.mostRecent()).toBeFalsy(); }); + + it("allows object arguments to be shallow cloned", function() { + var callTracker = new jasmineUnderTest.CallTracker(); + callTracker.saveArgumentsByValue(); + + var objectArg = {"foo": "bar"}, + arrayArg = ["foo", "bar"]; + + callTracker.track({object: {}, args: [objectArg, arrayArg, false, undefined, null, NaN, "", 0, 1.0]}); + + expect(callTracker.mostRecent().args[0]).not.toBe(objectArg); + expect(callTracker.mostRecent().args[0]).toEqual(objectArg); + expect(callTracker.mostRecent().args[1]).not.toBe(arrayArg); + expect(callTracker.mostRecent().args[1]).toEqual(arrayArg); + }); }); diff --git a/src/core/CallTracker.js b/src/core/CallTracker.js index b80e6a86..aead1403 100644 --- a/src/core/CallTracker.js +++ b/src/core/CallTracker.js @@ -1,9 +1,26 @@ -getJasmineRequireObj().CallTracker = function() { +getJasmineRequireObj().CallTracker = function(j$) { function CallTracker() { var calls = []; + var opts = {}; + + function argCloner(context) { + var clonedArgs = []; + var argsAsArray = j$.util.argsToArray(context.args); + for(var i = 0; i < argsAsArray.length; i++) { + if(Object.prototype.toString.apply(argsAsArray[i]).match(/^\[object/)) { + clonedArgs.push(j$.util.clone(argsAsArray[i])); + } else { + clonedArgs.push(argsAsArray[i]); + } + } + context.args = clonedArgs; + } this.track = function(context) { + if(opts.cloneArgs) { + argCloner(context); + } calls.push(context); }; @@ -44,6 +61,11 @@ getJasmineRequireObj().CallTracker = function() { this.reset = function() { calls = []; }; + + this.saveArgumentsByValue = function() { + opts.cloneArgs = true; + }; + } return CallTracker; diff --git a/src/core/requireCore.js b/src/core/requireCore.js index 571cf48a..51c82285 100644 --- a/src/core/requireCore.js +++ b/src/core/requireCore.js @@ -27,7 +27,7 @@ var getJasmineRequireObj = (function (jasmineGlobal) { j$.errors = jRequire.errors(); j$.Any = jRequire.Any(j$); j$.Anything = jRequire.Anything(j$); - j$.CallTracker = jRequire.CallTracker(); + j$.CallTracker = jRequire.CallTracker(j$); j$.MockDate = jRequire.MockDate(); j$.Clock = jRequire.Clock(); j$.DelayedFunctionScheduler = jRequire.DelayedFunctionScheduler();