|
var isCommonJS = typeof window == "undefined"; |
|
|
|
/** |
|
* Top level namespace for Jasmine, a lightweight JavaScript BDD/spec/testing framework. |
|
* |
|
* @namespace |
|
*/ |
|
var jasmine = {}; |
|
if (isCommonJS) exports.jasmine = jasmine; |
|
/** |
|
* @private |
|
*/ |
|
jasmine.unimplementedMethod_ = function() { |
|
throw new Error("unimplemented method"); |
|
}; |
|
|
|
/** |
|
* Use <code>jasmine.undefined</code> instead of <code>undefined</code>, since <code>undefined</code> is just |
|
* a plain old variable and may be redefined by somebody else. |
|
* |
|
* @private |
|
*/ |
|
jasmine.undefined = jasmine.___undefined___; |
|
|
|
/** |
|
* Show diagnostic messages in the console if set to true |
|
* |
|
*/ |
|
jasmine.VERBOSE = false; |
|
|
|
/** |
|
* Default interval in milliseconds for event loop yields (e.g. to allow network activity or to refresh the screen with the HTML-based runner). Small values here may result in slow test running. Zero means no updates until all tests have completed. |
|
* |
|
*/ |
|
jasmine.DEFAULT_UPDATE_INTERVAL = 250; |
|
|
|
/** |
|
* Default timeout interval in milliseconds for waitsFor() blocks. |
|
*/ |
|
jasmine.DEFAULT_TIMEOUT_INTERVAL = 5000; |
|
|
|
jasmine.getGlobal = function() { |
|
function getGlobal() { |
|
return this; |
|
} |
|
|
|
return getGlobal(); |
|
}; |
|
|
|
/** |
|
* Allows for bound functions to be compared. Internal use only. |
|
* |
|
* @ignore |
|
* @private |
|
* @param base {Object} bound 'this' for the function |
|
* @param name {Function} function to find |
|
*/ |
|
jasmine.bindOriginal_ = function(base, name) { |
|
var original = base[name]; |
|
if (original.apply) { |
|
return function() { |
|
return original.apply(base, arguments); |
|
}; |
|
} else { |
|
// IE support |
|
return jasmine.getGlobal()[name]; |
|
} |
|
}; |
|
|
|
jasmine.setTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'setTimeout'); |
|
jasmine.clearTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearTimeout'); |
|
jasmine.setInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'setInterval'); |
|
jasmine.clearInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearInterval'); |
|
|
|
jasmine.MessageResult = function(values) { |
|
this.type = 'log'; |
|
this.values = values; |
|
this.trace = new Error(); // todo: test better |
|
}; |
|
|
|
jasmine.MessageResult.prototype.toString = function() { |
|
var text = ""; |
|
for (var i = 0; i < this.values.length; i++) { |
|
if (i > 0) text += " "; |
|
if (jasmine.isString_(this.values[i])) { |
|
text += this.values[i]; |
|
} else { |
|
text += jasmine.pp(this.values[i]); |
|
} |
|
} |
|
return text; |
|
}; |
|
|
|
jasmine.ExpectationResult = function(params) { |
|
this.type = 'expect'; |
|
this.matcherName = params.matcherName; |
|
this.passed_ = params.passed; |
|
this.expected = params.expected; |
|
this.actual = params.actual; |
|
this.message = this.passed_ ? 'Passed.' : params.message; |
|
|
|
var trace = (params.trace || new Error(this.message)); |
|
this.trace = this.passed_ ? '' : trace; |
|
}; |
|
|
|
jasmine.ExpectationResult.prototype.toString = function () { |
|
return this.message; |
|
}; |
|
|
|
jasmine.ExpectationResult.prototype.passed = function () { |
|
return this.passed_; |
|
}; |
|
|
|
/** |
|
* Getter for the Jasmine environment. Ensures one gets created |
|
*/ |
|
jasmine.getEnv = function() { |
|
var env = jasmine.currentEnv_ = jasmine.currentEnv_ || new jasmine.Env(); |
|
return env; |
|
}; |
|
|
|
/** |
|
* @ignore |
|
* @private |
|
* @param value |
|
* @returns {Boolean} |
|
*/ |
|
jasmine.isArray_ = function(value) { |
|
return jasmine.isA_("Array", value); |
|
}; |
|
|
|
/** |
|
* @ignore |
|
* @private |
|
* @param value |
|
* @returns {Boolean} |
|
*/ |
|
jasmine.isString_ = function(value) { |
|
return jasmine.isA_("String", value); |
|
}; |
|
|
|
/** |
|
* @ignore |
|
* @private |
|
* @param value |
|
* @returns {Boolean} |
|
*/ |
|
jasmine.isNumber_ = function(value) { |
|
return jasmine.isA_("Number", value); |
|
}; |
|
|
|
/** |
|
* @ignore |
|
* @private |
|
* @param {String} typeName |
|
* @param value |
|
* @returns {Boolean} |
|
*/ |
|
jasmine.isA_ = function(typeName, value) { |
|
return Object.prototype.toString.apply(value) === '[object ' + typeName + ']'; |
|
}; |
|
|
|
/** |
|
* Pretty printer for expecations. Takes any object and turns it into a human-readable string. |
|
* |
|
* @param value {Object} an object to be outputted |
|
* @returns {String} |
|
*/ |
|
jasmine.pp = function(value) { |
|
var stringPrettyPrinter = new jasmine.StringPrettyPrinter(); |
|
stringPrettyPrinter.format(value); |
|
return stringPrettyPrinter.string; |
|
}; |
|
|
|
/** |
|
* Returns true if the object is a DOM Node. |
|
* |
|
* @param {Object} obj object to check |
|
* @returns {Boolean} |
|
*/ |
|
jasmine.isDomNode = function(obj) { |
|
return obj.nodeType > 0; |
|
}; |
|
|
|
/** |
|
* Returns a matchable 'generic' object of the class type. For use in expecations of type when values don't matter. |
|
* |
|
* @example |
|
* // don't care about which function is passed in, as long as it's a function |
|
* expect(mySpy).toHaveBeenCalledWith(jasmine.any(Function)); |
|
* |
|
* @param {Class} clazz |
|
* @returns matchable object of the type clazz |
|
*/ |
|
jasmine.any = function(clazz) { |
|
return new jasmine.Matchers.Any(clazz); |
|
}; |
|
|
|
/** |
|
* Returns a matchable subset of a JSON object. For use in expectations when you don't care about all of the |
|
* attributes on the object. |
|
* |
|
* @example |
|
* // don't care about any other attributes than foo. |
|
* expect(mySpy).toHaveBeenCalledWith(jasmine.objectContaining({foo: "bar"}); |
|
* |
|
* @param sample {Object} sample |
|
* @returns matchable object for the sample |
|
*/ |
|
jasmine.objectContaining = function (sample) { |
|
return new jasmine.Matchers.ObjectContaining(sample); |
|
}; |
|
|
|
/** |
|
* Jasmine Spies are test doubles that can act as stubs, spies, fakes or when used in an expecation, mocks. |
|
* |
|
* Spies should be created in test setup, before expectations. They can then be checked, using the standard Jasmine |
|
* expectation syntax. Spies can be checked if they were called or not and what the calling params were. |
|
* |
|
* A Spy has the following fields: wasCalled, callCount, mostRecentCall, and argsForCall (see docs). |
|
* |
|
* Spies are torn down at the end of every spec. |
|
* |
|
* Note: Do <b>not</b> call new jasmine.Spy() directly - a spy must be created using spyOn, jasmine.createSpy or jasmine.createSpyObj. |
|
* |
|
* @example |
|
* // a stub |
|
* var myStub = jasmine.createSpy('myStub'); // can be used anywhere |
|
* |
|
* // spy example |
|
* var foo = { |
|
* not: function(bool) { return !bool; } |
|
* } |
|
* |
|
* // actual foo.not will not be called, execution stops |
|
* spyOn(foo, 'not'); |
|
|
|
// foo.not spied upon, execution will continue to implementation |
|
* spyOn(foo, 'not').andCallThrough(); |
|
* |
|
* // fake example |
|
* var foo = { |
|
* not: function(bool) { return !bool; } |
|
* } |
|
* |
|
* // foo.not(val) will return val |
|
* spyOn(foo, 'not').andCallFake(function(value) {return value;}); |
|
* |
|
* // mock example |
|
* foo.not(7 == 7); |
|
* expect(foo.not).toHaveBeenCalled(); |
|
* expect(foo.not).toHaveBeenCalledWith(true); |
|
* |
|
* @constructor |
|
* @see spyOn, jasmine.createSpy, jasmine.createSpyObj |
|
* @param {String} name |
|
*/ |
|
jasmine.Spy = function(name) { |
|
/** |
|
* The name of the spy, if provided. |
|
*/ |
|
this.identity = name || 'unknown'; |
|
/** |
|
* Is this Object a spy? |
|
*/ |
|
this.isSpy = true; |
|
/** |
|
* The actual function this spy stubs. |
|
*/ |
|
this.plan = function() { |
|
}; |
|
/** |
|
* Tracking of the most recent call to the spy. |
|
* @example |
|
* var mySpy = jasmine.createSpy('foo'); |
|
* mySpy(1, 2); |
|
* mySpy.mostRecentCall.args = [1, 2]; |
|
*/ |
|
this.mostRecentCall = {}; |
|
|
|
/** |
|
* Holds arguments for each call to the spy, indexed by call count |
|
* @example |
|
* var mySpy = jasmine.createSpy('foo'); |
|
* mySpy(1, 2); |
|
* mySpy(7, 8); |
|
* mySpy.mostRecentCall.args = [7, 8]; |
|
* mySpy.argsForCall[0] = [1, 2]; |
|
* mySpy.argsForCall[1] = [7, 8]; |
|
*/ |
|
this.argsForCall = []; |
|
this.calls = []; |
|
}; |
|
|
|
/** |
|
* Tells a spy to call through to the actual implemenatation. |
|
* |
|
* @example |
|
* var foo = { |
|
* bar: function() { // do some stuff } |
|
* } |
|
* |
|
* // defining a spy on an existing property: foo.bar |
|
* spyOn(foo, 'bar').andCallThrough(); |
|
*/ |
|
jasmine.Spy.prototype.andCallThrough = function() { |
|
this.plan = this.originalValue; |
|
return this; |
|
}; |
|
|
|
/** |
|
* For setting the return value of a spy. |
|
* |
|
* @example |
|
* // defining a spy from scratch: foo() returns 'baz' |
|
* var foo = jasmine.createSpy('spy on foo').andReturn('baz'); |
|
* |
|
* // defining a spy on an existing property: foo.bar() returns 'baz' |
|
* spyOn(foo, 'bar').andReturn('baz'); |
|
* |
|
* @param {Object} value |
|
*/ |
|
jasmine.Spy.prototype.andReturn = function(value) { |
|
this.plan = function() { |
|
return value; |
|
}; |
|
return this; |
|
}; |
|
|
|
/** |
|
* For throwing an exception when a spy is called. |
|
* |
|
* @example |
|
* // defining a spy from scratch: foo() throws an exception w/ message 'ouch' |
|
* var foo = jasmine.createSpy('spy on foo').andThrow('baz'); |
|
* |
|
* // defining a spy on an existing property: foo.bar() throws an exception w/ message 'ouch' |
|
* spyOn(foo, 'bar').andThrow('baz'); |
|
* |
|
* @param {String} exceptionMsg |
|
*/ |
|
jasmine.Spy.prototype.andThrow = function(exceptionMsg) { |
|
this.plan = function() { |
|
throw exceptionMsg; |
|
}; |
|
return this; |
|
}; |
|
|
|
/** |
|
* Calls an alternate implementation when a spy is called. |
|
* |
|
* @example |
|
* var baz = function() { |
|
* // do some stuff, return something |
|
* } |
|
* // defining a spy from scratch: foo() calls the function baz |
|
* var foo = jasmine.createSpy('spy on foo').andCall(baz); |
|
* |
|
* // defining a spy on an existing property: foo.bar() calls an anonymnous function |
|
* spyOn(foo, 'bar').andCall(function() { return 'baz';} ); |
|
* |
|
* @param {Function} fakeFunc |
|
*/ |
|
jasmine.Spy.prototype.andCallFake = function(fakeFunc) { |
|
this.plan = fakeFunc; |
|
return this; |
|
}; |
|
|
|
/** |
|
* Resets all of a spy's the tracking variables so that it can be used again. |
|
* |
|
* @example |
|
* spyOn(foo, 'bar'); |
|
* |
|
* foo.bar(); |
|
* |
|
* expect(foo.bar.callCount).toEqual(1); |
|
* |
|
* foo.bar.reset(); |
|
* |
|
* expect(foo.bar.callCount).toEqual(0); |
|
*/ |
|
jasmine.Spy.prototype.reset = function() { |
|
this.wasCalled = false; |
|
this.callCount = 0; |
|
this.argsForCall = []; |
|
this.calls = []; |
|
this.mostRecentCall = {}; |
|
}; |
|
|
|
jasmine.createSpy = function(name) { |
|
|
|
var spyObj = function() { |
|
spyObj.wasCalled = true; |
|
spyObj.callCount++; |
|
var args = jasmine.util.argsToArray(arguments); |
|