以下是 jQuery内容滚动条拖拽滑动解锁代码 的示例演示效果:
部分效果截图:
HTML代码(index.html):
<html>
<head>
<title>jQuery内容滚动条拖拽滑动解锁代码</title>
<meta charset="utf-8">
<link href="lib/jasmine.css" type="text/css" rel="stylesheet">
<link href="lib/font-awesome/css/font-awesome.min.css" type="text/css" rel="stylesheet">
<script src="lib/jquery-1.10.2.js"></script>
<script src="lib/jquery.simulate.js"></script>
<script src="lib/jasmine.js"></script>
<script src="lib/jasmine-jsreporter.js"></script>
<script src="lib/jasmine-html.js"></script>
<script src="lib/jasmine-jquery.js"></script>
<link href="src/dragdealer.css" type="text/css" rel="stylesheet">
<script src="src/dragdealer.js"></script>
<script src="spec/helpers.js"></script>
<script src="spec/matchers.js"></script>
<script src="spec/optionsSpec.js"></script>
<script src="spec/draggingSpec.js"></script>
<!--[if gt IE 9]><!-->
<script src="spec/touchDraggingSpec.js"></script>
<!--<![endif]-->
<script src="spec/callbacksSpec.js"></script>
<script src="spec/apiSpec.js"></script>
<script src="spec/resizingSpec.js"></script>
<script src="spec/eventsSpec.js"></script>
<script src="spec/setup.js"></script>
<script src="spec/browser-runner.js"></script>
<link href="demo/style/index.css" type="text/css" rel="stylesheet">
<link href="demo/style/jasmine-reporter.css" type="text/css" rel="stylesheet">
<link href="demo/style/demos.css" type="text/css" rel="stylesheet">
<script src="demo/script/index.js"></script>
<script src="demo/script/demos.js"></script>
</head>
<body>
<div id="main-slider" class="dragdealer">
<div class="specs-tab">
<ul class="specs-bullets"></ul>
<p class="specs-summary"></p>
</div>
<div class="handle red-bar">
<h1><strong>Dragdealer</strong>.js</h1>
</div>
</div>
<div id="content">
<div class="content-slides">
<div class="slide demo">
<div class="inner-wrapper">
<h3 id="demos">Demos1</h3>
<div id="demo-simple-slider" class="dragdealer">
<div class="handle red-bar">drag me</div>
</div>
<h3 id="demos">Demos2</h3>
<div id="just-a-slider" class="dragdealer">
<div class="handle red-bar">
<span class="value"></span>%
</div>
</div>
<h3 id="demos">Demos3</h3>
<div class="content-scroller">
<div id="content-scroller" class="dragdealer">
<div class="handle red-bar">
<span class="value"><i class="fa fa-bars"></i></span>
</div>
</div>
<div class="content-mask">
<div class="content-body">
<p>It was all a dream<br>
I used to read Word Up magazine<br>
Salt 'n' Pepa and Heavy D up in the limousine<br>
Hangin pictures on my wall<br>
Every Saturday Rap Attack, Mr. Magic, Marley Marl<br>
I let my tape rock 'til my tape popped<br>
Smoking weed and Bambu, sipping on Private Stock<br>
Way back, when I had the red and black lumberjack<br>
With the hat to match<br>
Remember Rappin Duke? duh-ha, duh-ha<br>
You never thought that hip hop would take it this far<br>
Now I'm in the limelight cause I rhyme tight<br>
Time to get paid, blow up like the World Trade<br>
Born sinner, the opposite of a winner<br>
Remember when I used to eat sardines for dinner<br>
Peace to Ron G, Brucey B, Kid Capri<br>
Funkmaster Flex, Lovebug Starski (wassup)<br>
I'm blowing up like you thought I would<br>
Call the crib, same number same hood (that's right)<br>
It's all good (it's all good)<br>
And if you don't know, now you know, nigga</p>
<p>I made the change from a common thief<br>
To up close and personal with Robin Leach<br>
And I'm far from cheap, I smoke skunk with my peeps all day<br>
Spread love, it's the Brooklyn way<br>
The Moet and Alizé keep me pissy<br>
Girls used to diss me<br>
Now they write letters cause they miss me<br>
I never thought it could happen, this rapping stuff<br>
I was too used to packing gats and stuff<br>
Now honeys play me close like butter play toast<br>
From the Mississippi down to the east coast<br>
Condos in Queens, indo for weeks<br>
Sold out seats to hear Biggie Smalls speak<br>
Living life without fear<br>
Putting 5 karats in my baby girl's ears<br>
Lunches, brunches, interviews by the pool<br>
Considered a fool cause I dropped out of high school<br>
Stereotypes of a black male misunderstood<br>
And it's still all good<br>
Uh...and if you don't know, now you know, nigga</p>
<p>Super Nintendo, Sega Genesis<br>
When I was dead broke, man I couldn't picture this<br>
50-inch screen, money green leather sofa<br>
Got two rides, a limousine with a chauffeur<br>
Phone bill about two G's flat<br>
No need to worry, my accountant handles that<br>
And my whole crew is lounging<br>
Celebrating every day, no more public housing<br>
Thinking back on my one-room shack<br>
Now my mom pimps a Ac with minks on her back<br>
And she loves to show me off, of course<br>
Smiles every time my face is up in The Source<br>
We used to fuss when the landlord dissed us<br>
No heat, wonder why Christmas missed us<br>
Birthdays was the worst days<br>
Now we sip champagne when we thirst-ay<br>
Uh, damn right I like the life I live<br>
Cause I went from negative to positive<br>
And it's all</p>
<p>...and if you don't know, now you know, niggaaa</p>
</div>
</div>
</div>
<h3 id="demos">Demos4</h3>
<div class="slide-to-unlock old-slider">
<div id="slide-to-unlock-old" class="dragdealer">
<div class="slide-text">slide to unlock</div>
<div class="handle"></div>
</div>
</div>
<h3 id="demos">Demos5</h3>
<div class="slide-to-unlock new-slider">
<div id="slide-to-unlock-new" class="dragdealer">
<div class="handle">
<div class="slide-text"><i class="fa fa-angle-right"></i> slide to unlock</div>
</div>
</div>
</div>
<h3 id="demos">Demos6</h3>
<div id="image-carousel" class="dragdealer">
<div class="handle">
<div class="slide img1">
<div class="info">
<p class="title">Aston Martin DB4</p>
<p class="description"><strong>1959</strong> — 3.7L, 240hp</p>
</div>
</div>
<div class="slide img2">
<div class="info">
<p class="title">Mercedes-Benz 300SL</p>
<p class="description"><strong>1956</strong> — 2996cc, 212-222hp</p>
</div>
</div>
<div class="slide img3">
<div class="info">
<p class="title">Jaguar E-Type</p>
<p class="description"><strong>1966</strong> — 3.8L, 265bhp</p>
</div>
</div>
<div class="slide img4">
<div class="info">
<p class="title">Maserati A6</p>
<p class="description"><strong>1950</strong> — 2L, 120bhp</p>
</div>
</div>
</div>
</div>
<h3 id="demos">Demos7</h3>
<div id="canvas-mask" class="dragdealer">
<div class="handle">
<div class="page">
<p class="menu">
<a href="#" data-x="0" data-y="1">Two-dimensional</a> |
<a href="#" data-x="1" data-y="1">Elastic</a> |
<a href="#" data-x="1" data-y="0">Interactive</a> |
<strong>Open</strong>
</p>
<p class="body">
Dragdealer is <strong>open source</strong>, <br >
see you on <a href="#">GitHub</a>
</p>
</div>
<div class="page">
<p class="menu">
<a href="#" data-x="0" data-y="1">Two-dimensional</a> |
<a href="#" data-x="1" data-y="1">Elastic</a> |
<strong>Interactive</strong> |
<a href="#" data-x="0" data-y="0">Open</a>
</p>
<p class="body">
The dragged surface can host <strong>rich content</strong>, <br>
including links for scrolling inside itself
</p>
</div>
<div class="page">
<p class="menu">
<strong>Two-dimensional</strong> |
<a href="#" data-x="1" data-y="1">Elastic</a> |
<a href="#" data-x="1" data-y="0">Interactive</a> |
<a href="#" data-x="0" data-y="0">Open</a>
</p>
<p class="body">
The masked content can be discovered through <br>
both <strong>horizontal and vertical dragging</strong>
</p>
</div>
<div class="page">
<p class="menu">
<a href="#" data-x="0" data-y="1">Two-dimensional</a> |
<strong>Elastic</strong> |
<a href="#" data-x="1" data-y="0">Interactive</a> |
<a href="#" data-x="0" data-y="0">Open</a>
</p>
<p class="body">
The surface boundaries have an <strong>elastic ease</strong> and <br>
the corners can be slightly pulled inwards
</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
JS代码(jasmine.js):
var isCommonJS = typeof window == "undefined" && typeof exports == "object";
/** * 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;
/** * Maximum levels of nesting that will be included when an object is pretty-printed */
jasmine.MAX_PRETTY_PRINT_DEPTH = 40;
/** * Default timeout interval in milliseconds for waitsFor() blocks. */
jasmine.DEFAULT_TIMEOUT_INTERVAL = 5000;
/** * By default exceptions thrown in the context of a test are caught by jasmine so that it can run the remaining tests in the suite. * Set to false to let the exception bubble up in the browser. * */
jasmine.CATCH_EXCEPTIONS = true;
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);
spyObj.mostRecentCall.object = this;
spyObj.mostRecentCall.args = args;
spyObj.argsForCall.push(args);
spyObj.calls.push({
object:this,args:args}
);
return spyObj.plan.apply(this,arguments);
}
;
var spy = new jasmine.Spy(name);
for (var prop in spy){
spyObj[prop] = spy[prop];
}
spyObj.reset();
return spyObj;
}
;
/** * Determines whether an object is a spy. * * @param{
jasmine.Spy|Object}
putativeSpy * @returns{
Boolean}
*/
jasmine.isSpy = function(putativeSpy){
return putativeSpy && putativeSpy.isSpy;
}
;
/** * Creates a more complicated spy:an Object that has every property a function that is a spy. Used for stubbing something * large in one call. * * @param{
String}
baseName name of spy class * @param{
Array}
methodNames array of names of methods to make spies */
jasmine.createSpyObj = function(baseName,methodNames){
if (!jasmine.isArray_(methodNames) || methodNames.length === 0){
throw new Error('createSpyObj requires a non-empty array of method names to create spies for');
}
var obj ={
}
;
for (var i = 0;
i < methodNames.length;
i++){
obj[methodNames[i]] = jasmine.createSpy(baseName + '.' + methodNames[i]);
}
return obj;
}
;
/** * All parameters are pretty-printed and concatenated together,then written to the current spec's output. * * Be careful not to leave calls to <code>jasmine.log</code> in production code. */
jasmine.log = function(){
var spec = jasmine.getEnv().currentSpec;
spec.log.apply(spec,arguments);
}
;
/** * Function that installs a spy on an existing object's method name. Used within a Spec to create a spy. * * @example * // spy example * var foo ={
* not:function(bool){
return !bool;
}
*}
* spyOn(foo,'not');
// actual foo.not will not be called,execution stops * * @see jasmine.createSpy * @param obj * @param methodName * @return{
jasmine.Spy}
a Jasmine spy that can be chained with all spy methods */
var spyOn = function(obj,methodName){
return jasmine.getEnv().currentSpec.spyOn(obj,methodName);
}
;
if (isCommonJS) exports.spyOn = spyOn;
/** * Creates a Jasmine spec that will be added to the current suite. * * // TODO:pending tests * * @example * it('should be true',function(){
* expect(true).toEqual(true);
*}
);
* * @param{
String}
desc description of this specification * @param{
Function}
func defines the preconditions and expectations of the spec */
var it = function(desc,func){
return jasmine.getEnv().it(desc,func);
}
;
if (isCommonJS) exports.it = it;
/** * Creates a <em>disabled</em> Jasmine spec. * * A convenience method that allows existing specs to be disabled temporarily during development. * * @param{
String}
desc description of this specification * @param{
Function}
func defines the preconditions and expectations of the spec */
var xit = function(desc,func){
return jasmine.getEnv().xit(desc,func);
}
;
if (isCommonJS) exports.xit = xit;
/** * Starts a chain for a Jasmine expectation. * * It is passed an Object that is the actual value and should chain to one of the many * jasmine.Matchers functions. * * @param{
Object}
actual Actual value to test against and expected value * @return{
jasmine.Matchers}
*/
var expect = function(actual){
return jasmine.getEnv().currentSpec.expect(actual);
}
;
if (isCommonJS) exports.expect = expect;
/** * Defines part of a jasmine spec. Used in cominbination with waits or waitsFor in asynchrnous specs. * * @param{
Function}
func Function that defines part of a jasmine spec. */
var runs = function(func){
jasmine.getEnv().currentSpec.runs(func);
}
;
if (isCommonJS) exports.runs = runs;
/** * Waits a fixed time period before moving to the next block. * * @deprecated Use waitsFor() instead * @param{
Number}
timeout milliseconds to wait */
var waits = function(timeout){
jasmine.getEnv().currentSpec.waits(timeout);
}
;
if (isCommonJS) exports.waits = waits;
/** * Waits for the latchFunction to return true before proceeding to the next block. * * @param{
Function}
latchFunction * @param{
String}
optional_timeoutMessage * @param{
Number}
optional_timeout */
var waitsFor = function(latchFunction,optional_timeoutMessage,optional_timeout){
jasmine.getEnv().currentSpec.waitsFor.apply(jasmine.getEnv().currentSpec,arguments);
}
;
if (isCommonJS) exports.waitsFor = waitsFor;
/** * A function that is called before each spec in a suite. * * Used for spec setup,including validating assumptions. * * @param{
Function}
beforeEachFunction */
var beforeEach = function(beforeEachFunction){
jasmine.getEnv().beforeEach(beforeEachFunction);
}
;
if (isCommonJS) exports.beforeEach = beforeEach;
/** * A function that is called after each spec in a suite. * * Used for restoring any state that is hijacked during spec execution. * * @param{
Function}
afterEachFunction */
var afterEach = function(afterEachFunction){
jasmine.getEnv().afterEach(afterEachFunction);
}
;
if (isCommonJS) exports.afterEach = afterEach;
/** * Defines a suite of specifications. * * Stores the description and all defined specs in the Jasmine environment as one suite of specs. Variables declared * are accessible by calls to beforeEach,it,and afterEach. Describe blocks can be nested,allowing for specialization * of setup in some tests. * * @example * // TODO:a simple suite * * // TODO:a simple suite with a nested describe block * * @param{
String}
description A string,usually the class under test. * @param{
Function}
specDefinitions function that defines several specs. */
var describe = function(description,specDefinitions){
return jasmine.getEnv().describe(description,specDefinitions);
}
;
if (isCommonJS) exports.describe = describe;
/** * Disables a suite of specifications. Used to disable some suites in a file,or files,temporarily during development. * * @param{
String}
description A string,usually the class under test. * @param{
Function}
specDefinitions function that defines several specs. */
var xdescribe = function(description,specDefinitions){
return jasmine.getEnv().xdescribe(description,specDefinitions);
}
;
if (isCommonJS) exports.xdescribe = xdescribe;
// Provide the XMLHttpRequest class for IE 5.x-6.x:jasmine.XmlHttpRequest = (typeof XMLHttpRequest == "undefined") ? function(){
function tryIt(f){
try{
return f();
}
catch(e){
}
return null;
}
var xhr = tryIt(function(){
return new ActiveXObject("Msxml2.XMLHTTP.6.0");
}
) || tryIt(function(){
return new ActiveXObject("Msxml2.XMLHTTP.3.0");
}
) || tryIt(function(){
return new ActiveXObject("Msxml2.XMLHTTP");
}
) || tryIt(function(){
return new ActiveXObject("Microsoft.XMLHTTP");
}
);
if (!xhr) throw new Error("This browser does not support XMLHttpRequest.");
return xhr;
}
:XMLHttpRequest;
/** * @namespace */
jasmine.util ={
}
;
/** * Declare that a child class inherit it's prototype from the parent class. * * @private * @param{
Function}
childClass * @param{
Function}
parentClass */
jasmine.util.inherit = function(childClass,parentClass){
/** * @private */
var subclass = function(){
}
;
subclass.prototype = parentClass.prototype;
childClass.prototype = new subclass();
}
;
jasmine.util.formatException = function(e){
var lineNumber;
if (e.line){
lineNumber = e.line;
}
else if (e.lineNumber){
lineNumber = e.lineNumber;
}
var file;
if (e.sourceURL){
file = e.sourceURL;
}
else if (e.fileName){
file = e.fileName;
}
var message = (e.name && e.message) ? (e.name + ':' + e.message):e.toString();
if (file && lineNumber){
message += ' in ' + file + ' (line ' + lineNumber + ')';
}
return message;
}
;
jasmine.util.htmlEscape = function(str){
if (!str) return str;
return str.replace(/&/g,'&
') .replace(/</g,'<
') .replace(/>/g,'>
');
}
;
jasmine.util.argsToArray = function(args){
var arrayOfArgs = [];
for (var i = 0;
i < args.length;
i++) arrayOfArgs.push(args[i]);
return arrayOfArgs;
}
;
jasmine.util.extend = function(destination,source){
for (var property in source) destination[property] = source[property];
return destination;
}
;
/** * Environment for Jasmine * * @constructor */
jasmine.Env = function(){
this.currentSpec = null;
this.currentSuite = null;
this.currentRunner_ = new jasmine.Runner(this);
this.reporter = new jasmine.MultiReporter();
this.updateInterval = jasmine.DEFAULT_UPDATE_INTERVAL;
this.defaultTimeoutInterval = jasmine.DEFAULT_TIMEOUT_INTERVAL;
this.lastUpdate = 0;
this.specFilter = function(){
return true;
}
;
this.nextSpecId_ = 0;
this.nextSuiteId_ = 0;
this.equalityTesters_ = [];
// wrap matchers this.matchersClass = function(){
jasmine.Matchers.apply(this,arguments);
}
;
jasmine.util.inherit(this.matchersClass,jasmine.Matchers);
jasmine.Matchers.wrapInto_(jasmine.Matchers.prototype,this.matchersClass);
}
;
jasmine.Env.prototype.setTimeout = jasmine.setTimeout;
jasmine.Env.prototype.clearTimeout = jasmine.clearTimeout;
jasmine.Env.prototype.setInterval = jasmine.setInterval;
jasmine.Env.prototype.clearInterval = jasmine.clearInterval;
/** * @returns an object containing jasmine version build info,if set. */
jasmine.Env.prototype.version = function (){
if (jasmine.version_){
return jasmine.version_;
}
else{
throw new Error('Version not set');
}
}
;
/** * @returns string containing jasmine version build info,if set. */
jasmine.Env.prototype.versionString = function(){
if (!jasmine.version_){
return "version unknown";
}
var version = this.version();
var versionString = version.major + "." + version.minor + "." + version.build;
if (version.release_candidate){
versionString += ".rc" + version.release_candidate;
}
versionString += " revision " + version.revision;
return versionString;
}
;
/** * @returns a sequential integer starting at 0 */
jasmine.Env.prototype.nextSpecId = function (){
return this.nextSpecId_++;
}
;
/** * @returns a sequential integer starting at 0 */
jasmine.Env.prototype.nextSuiteId = function (){
return this.nextSuiteId_++;
}
;
/** * Register a reporter to receive status updates from Jasmine. * @param{
jasmine.Reporter}
reporter An object which will receive status updates. */
jasmine.Env.prototype.addReporter = function(reporter){
this.reporter.addReporter(reporter);
}
;
jasmine.Env.prototype.execute = function(){
this.currentRunner_.execute();
}
;
jasmine.Env.prototype.describe = function(description,specDefinitions){
var suite = new jasmine.Suite(this,description,specDefinitions,this.currentSuite);
var parentSuite = this.currentSuite;
if (parentSuite){
parentSuite.add(suite);
}
else{
this.currentRunner_.add(suite);
}
this.currentSuite = suite;
var declarationError = null;
try{
specDefinitions.call(suite);
}
catch(e){
declarationError = e;
}
if (declarationError){
this.it("encountered a declaration exception",function(){
throw declarationError;
}
);
}
this.currentSuite = parentSuite;
return suite;
}
;
jasmine.Env.prototype.beforeEach = function(beforeEachFunction){
if (this.currentSuite){
this.currentSuite.beforeEach(beforeEachFunction);
}
else{
this.currentRunner_.beforeEach(beforeEachFunction);
}
}
;
jasmine.Env.prototype.currentRunner = function (){
return this.currentRunner_;
}
;
jasmine.Env.prototype.afterEach = function(afterEachFunction){
if (this.currentSuite){
this.currentSuite.afterEach(afterEachFunction);
}
else{
this.currentRunner_.afterEach(afterEachFunction);
}
}
;
jasmine.Env.prototype.xdescribe = function(desc,specDefinitions){
return{
execute:function(){
}
}
;
}
;
jasmine.Env.prototype.it = function(description,func){
var spec = new jasmine.Spec(this,this.currentSuite,description);
this.currentSuite.add(spec);
this.currentSpec = spec;
if (func){
spec.runs(func);
}
return spec;
}
;
jasmine.Env.prototype.xit = function(desc,func){
return{
id:this.nextSpecId(),runs:function(){
}
}
;
}
;
jasmine.Env.prototype.compareRegExps_ = function(a,b,mismatchKeys,mismatchValues){
if (a.source != b.source) mismatchValues.push("expected pattern /" + b.source + "/ is not equal to the pattern /" + a.source + "/");
if (a.ignoreCase != b.ignoreCase) mismatchValues.push("expected modifier i was" + (b.ignoreCase ? " ":" not ") + "set and does not equal the origin modifier");
if (a.global != b.global) mismatchValues.push("expected modifier g was" + (b.global ? " ":" not ") + "set and does not equal the origin modifier");
if (a.multiline != b.multiline) mismatchValues.push("expected modifier m was" + (b.multiline ? " ":" not ") + "set and does not equal the origin modifier");
if (a.sticky != b.sticky) mismatchValues.push("expected modifier y was" + (b.sticky ? " ":" not ") + "set and does not equal the origin modifier");
return (mismatchValues.length === 0);
}
;
jasmine.Env.prototype.compareObjects_ = function(a,b,mismatchKeys,mismatchValues){
if (a.__Jasmine_been_here_before__ === b && b.__Jasmine_been_here_before__ === a){
return true;
}
a.__Jasmine_been_here_before__ = b;
b.__Jasmine_been_here_before__ = a;
var hasKey = function(obj,keyName){
return obj !== null && obj[keyName] !== jasmine.undefined;
}
;
for (var property in b){
if (!hasKey(a,property) && hasKey(b,property)){
mismatchKeys.push("expected has key '" + property + "',but missing from actual.");
}
}
for (property in a){
if (!hasKey(b,property) && hasKey(a,property)){
mismatchKeys.push("expected missing key '" + property + "',but present in actual.");
}
}
for (property in b){
if (property == '__Jasmine_been_here_before__') continue;
if (!this.equals_(a[property],b[property],mismatchKeys,mismatchValues)){
mismatchValues.push("'" + property + "' was '" + (b[property] ? jasmine.util.htmlEscape(b[property].toString()):b[property]) + "' in expected,but was '" + (a[property] ? jasmine.util.htmlEscape(a[property].toString()):a[property]) + "' in actual.");
}
}
if (jasmine.isArray_(a) && jasmine.isArray_(b) && a.length != b.length){
mismatchValues.push("arrays were not the same length");
}
delete a.__Jasmine_been_here_before__;
delete b.__Jasmine_been_here_before__;
return (mismatchKeys.length === 0 && mismatchValues.length === 0);
}
;
jasmine.Env.prototype.equals_ = function(a,b,mismatchKeys,mismatchValues){
mismatchKeys = mismatchKeys || [];
mismatchValues = mismatchValues || [];
for (var i = 0;
i < this.equalityTesters_.length;
i++){
var equalityTester = this.equalityTesters_[i];
var result = equalityTester(a,b,this,mismatchKeys,mismatchValues);
if (result !== jasmine.undefined) return result;
}
if (a === b) return true;
if (a === jasmine.undefined || a === null || b === jasmine.undefined || b === null){
return (a == jasmine.undefined && b == jasmine.undefined);
}
if (jasmine.isDomNode(a) && jasmine.isDomNode(b)){
return a === b;
}
if (a instanceof Date && b instanceof Date){
return a.getTime() == b.getTime();
}
if (a.jasmineMatches){
return a.jasmineMatches(b);
}
if (b.jasmineMatches){
return b.jasmineMatches(a);
}
if (a instanceof jasmine.Matchers.ObjectContaining){
return a.matches(b);
}
if (b instanceof jasmine.Matchers.ObjectContaining){
return b.matches(a);
}
if (jasmine.isString_(a) && jasmine.isString_(b)){
return (a == b);
}
if (jasmine.isNumber_(a) && jasmine.isNumber_(b)){
return (a == b);
}
if (a instanceof RegExp && b instanceof RegExp){
return this.compareRegExps_(a,b,mismatchKeys,mismatchValues);
}
if (typeof a === "object" && typeof b === "object"){
return this.compareObjects_(a,b,mismatchKeys,mismatchValues);
}
//Straight check return (a === b);
}
;
jasmine.Env.prototype.contains_ = function(haystack,needle){
if (jasmine.isArray_(haystack)){
for (var i = 0;
i < haystack.length;
i++){
if (this.equals_(haystack[i],needle)) return true;
}
return false;
}
return haystack.indexOf(needle) >= 0;
}
;
jasmine.Env.prototype.addEqualityTester = function(equalityTester){
this.equalityTesters_.push(equalityTester);
}
;
/** No-op base class for Jasmine reporters. * * @constructor */
jasmine.Reporter = function(){
}
;
//noinspection JSUnusedLocalSymbolsjasmine.Reporter.prototype.reportRunnerStarting = function(runner){
}
;
//noinspection JSUnusedLocalSymbolsjasmine.Reporter.prototype.reportRunnerResults = function(runner){
}
;
//noinspection JSUnusedLocalSymbolsjasmine.Reporter.prototype.reportSuiteResults = function(suite){
}
;
//noinspection JSUnusedLocalSymbolsjasmine.Reporter.prototype.reportSpecStarting = function(spec){
}
;
//noinspection JSUnusedLocalSymbolsjasmine.Reporter.prototype.reportSpecResults = function(spec){
}
;
//noinspection JSUnusedLocalSymbolsjasmine.Reporter.prototype.log = function(str){
}
;
/** * Blocks are functions with executable code that make up a spec. * * @constructor * @param{
jasmine.Env}
env * @param{
Function}
func * @param{
jasmine.Spec}
spec */
jasmine.Block = function(env,func,spec){
this.env = env;
this.func = func;
this.spec = spec;
}
;
jasmine.Block.prototype.execute = function(onComplete){
if (!jasmine.CATCH_EXCEPTIONS){
this.func.apply(this.spec);
}
else{
try{
this.func.apply(this.spec);
}
catch (e){
this.spec.fail(e);
}
}
onComplete();
}
;
/** JavaScript API reporter. * * @constructor */
jasmine.JsApiReporter = function(){
this.started = false;
this.finished = false;
this.suites_ = [];
this.results_ ={
}
;
}
;
jasmine.JsApiReporter.prototype.reportRunnerStarting = function(runner){
this.started = true;
var suites = runner.topLevelSuites();
for (var i = 0;
i < suites.length;
i++){
var suite = suites[i];
this.suites_.push(this.summarize_(suite));
}
}
;
jasmine.JsApiReporter.prototype.suites = function(){
return this.suites_;
}
;
jasmine.JsApiReporter.prototype.summarize_ = function(suiteOrSpec){
var isSuite = suiteOrSpec instanceof jasmine.Suite;
var summary ={
id:suiteOrSpec.id,name:suiteOrSpec.description,type:isSuite ? 'suite':'spec',children:[]}
;
if (isSuite){
var children = suiteOrSpec.children();
for (var i = 0;
i < children.length;
i++){
summary.children.push(this.summarize_(children[i]));
}
}
return summary;
}
;
jasmine.JsApiReporter.prototype.results = function(){
return this.results_;
}
;
jasmine.JsApiReporter.prototype.resultsForSpec = function(specId){
return this.results_[specId];
}
;
//noinspection JSUnusedLocalSymbolsjasmine.JsApiReporter.prototype.reportRunnerResults = function(runner){
this.finished = true;
}
;
//noinspection JSUnusedLocalSymbolsjasmine.JsApiReporter.prototype.reportSuiteResults = function(suite){
}
;
//noinspection JSUnusedLocalSymbolsjasmine.JsApiReporter.prototype.reportSpecResults = function(spec){
this.results_[spec.id] ={
messages:spec.results().getItems(),result:spec.results().failedCount > 0 ? "failed":"passed"}
;
}
;
//noinspection JSUnusedLocalSymbolsjasmine.JsApiReporter.prototype.log = function(str){
}
;
jasmine.JsApiReporter.prototype.resultsForSpecs = function(specIds){
var results ={
}
;
for (var i = 0;
i < specIds.length;
i++){
var specId = specIds[i];
results[specId] = this.summarizeResult_(this.results_[specId]);
}
return results;
}
;
jasmine.JsApiReporter.prototype.summarizeResult_ = function(result){
var summaryMessages = [];
var messagesLength = result.messages.length;
for (var messageIndex = 0;
messageIndex < messagesLength;
messageIndex++){
var resultMessage = result.messages[messageIndex];
summaryMessages.push({
text:resultMessage.type == 'log' ? resultMessage.toString():jasmine.undefined,passed:resultMessage.passed ? resultMessage.passed():true,type:resultMessage.type,message:resultMessage.message,trace:{
stack:resultMessage.passed && !resultMessage.passed() ? resultMessage.trace.stack:jasmine.undefined}
}
);
}
return{
result:result.result,messages:summaryMessages}
;
}
;
/** * @constructor * @param{
jasmine.Env}
env * @param actual * @param{
jasmine.Spec}
spec */
jasmine.Matchers = function(env,actual,spec,opt_isNot){
this.env = env;
this.actual = actual;
this.spec = spec;
this.isNot = opt_isNot || false;
this.reportWasCalled_ = false;
}
;
// todo:@deprecated as of Jasmine 0.11,remove soon [xw]jasmine.Matchers.pp = function(str){
throw new Error("jasmine.Matchers.pp() is no longer supported,please use jasmine.pp() instead!");
}
;
// todo:@deprecated Deprecated as of Jasmine 0.10. Rewrite your custom matchers to return true or false. [xw]jasmine.Matchers.prototype.report = function(result,failing_message,details){
throw new Error("As of jasmine 0.11,custom matchers must be implemented differently -- please see jasmine docs");
}
;
jasmine.Matchers.wrapInto_ = function(prototype,matchersClass){
for (var methodName in prototype){
if (methodName == 'report') continue;
var orig = prototype[methodName];
matchersClass.prototype[methodName] = jasmine.Matchers.matcherFn_(methodName,orig);
}
}
;
jasmine.Matchers.matcherFn_ = function(matcherName,matcherFunction){
return function(){
var matcherArgs = jasmine.util.argsToArray(arguments);
var result = matcherFunction.apply(this,arguments);
if (this.isNot){
result = !result;
}
if (this.reportWasCalled_) return result;
var message;
if (!result){
if (this.message){
message = this.message.apply(this,arguments);
if (jasmine.isArray_(message)){
message = message[this.isNot ? 1:0];
}
}
else{
var englishyPredicate = matcherName.replace(/[A-Z]/g,function(s){
return ' ' + s.toLowerCase();
}
);
message = "Expected " + jasmine.pp(this.actual) + (this.isNot ? " not ":" ") + englishyPredicate;
if (matcherArgs.length > 0){
for (var i = 0;
i < matcherArgs.length;
i++){
if (i > 0) message += ",";
message += " " + jasmine.pp(matcherArgs[i]);
}
}
message += ".";
}
}
var expectationResult = new jasmine.ExpectationResult({
matcherName:matcherName,passed:result,expected:matcherArgs.length > 1 ? matcherArgs:matcherArgs[0],actual:this.actual,message:message}
);
this.spec.addMatcherResult(expectationResult);
return jasmine.undefined;
}
;
}
;
/** * toBe:compares the actual to the expected using === * @param expected */
jasmine.Matchers.prototype.toBe = function(expected){
return this.actual === expected;
}
;
/** * toNotBe:compares the actual to the expected using !== * @param expected * @deprecated as of 1.0. Use not.toBe() instead. */
jasmine.Matchers.prototype.toNotBe = function(expected){
return this.actual !== expected;
}
;
/** * toEqual:compares the actual to the expected using common sense equality. Handles Objects,Arrays,etc. * * @param expected */
jasmine.Matchers.prototype.toEqual = function(expected){
return this.env.equals_(this.actual,expected);
}
;
/** * toNotEqual:compares the actual to the expected using the ! of jasmine.Matchers.toEqual * @param expected * @deprecated as of 1.0. Use not.toEqual() instead. */
jasmine.Matchers.prototype.toNotEqual = function(expected){
return !this.env.equals_(this.actual,expected);
}
;
/** * Matcher that compares the actual to the expected using a regular expression. Constructs a RegExp,so takes * a pattern or a String. * * @param expected */
jasmine.Matchers.prototype.toMatch = function(expected){
return new RegExp(expected).test(this.actual);
}
;
/** * Matcher that compares the actual to the expected using the boolean inverse of jasmine.Matchers.toMatch * @param expected * @deprecated as of 1.0. Use not.toMatch() instead. */
jasmine.Matchers.prototype.toNotMatch = function(expected){
return !(new RegExp(expected).test(this.actual));
}
;
/** * Matcher that compares the actual to jasmine.undefined. */
jasmine.Matchers.prototype.toBeDefined = function(){
return (this.actual !== jasmine.undefined);
}
;
/** * Matcher that compares the actual to jasmine.undefined. */
jasmine.Matchers.prototype.toBeUndefined = function(){
return (this.actual === jasmine.undefined);
}
;
/** * Matcher that compares the actual to null. */
jasmine.Matchers.prototype.toBeNull = function(){
return (this.actual === null);
}
;
/** * Matcher that compares the actual to NaN. */
jasmine.Matchers.prototype.toBeNaN = function(){
this.message = function(){
return [ "Expected " + jasmine.pp(this.actual) + " to be NaN." ];
}
;
return (this.actual !== this.actual);
}
;
/** * Matcher that boolean not-nots the actual. */
jasmine.Matchers.prototype.toBeTruthy = function(){
return !!this.actual;
}
;
/** * Matcher that boolean nots the actual. */
jasmine.Matchers.prototype.toBeFalsy = function(){
return !this.actual;
}
;
/** * Matcher that checks to see if the actual,a Jasmine spy,was called. */
jasmine.Matchers.prototype.toHaveBeenCalled = function(){
if (arguments.length > 0){
throw new Error('toHaveBeenCalled does not take arguments,use toHaveBeenCalledWith');
}
if (!jasmine.isSpy(this.actual)){
throw new Error('Expected a spy,but got ' + jasmine.pp(this.actual) + '.');
}
this.message = function(){
return [ "Expected spy " + this.actual.identity + " to have been called.","Expected spy " + this.actual.identity + " not to have been called." ];
}
;
return this.actual.wasCalled;
}
;
/** @deprecated Use expect(xxx).toHaveBeenCalled() instead */
jasmine.Matchers.prototype.wasCalled = jasmine.Matchers.prototype.toHaveBeenCalled;
/** * Matcher that checks to see if the actual,a Jasmine spy,was not called. * * @deprecated Use expect(xxx).not.toHaveBeenCalled() instead */
jasmine.Matchers.prototype.wasNotCalled = function(){
if (arguments.length > 0){
throw new Error('wasNotCalled does not take arguments');
}
if (!jasmine.isSpy(this.actual)){
throw new Error('Expected a spy,but got ' + jasmine.pp(this.actual) + '.');
}
this.message = function(){
return [ "Expected spy " + this.actual.identity + " to not have been called.","Expected spy " + this.actual.identity + " to have been called." ];
}
;
return !this.actual.wasCalled;
}
;
/** * Matcher that checks to see if the actual,a Jasmine spy,was called with a set of parameters. * * @example * */
jasmine.Matchers.prototype.toHaveBeenCalledWith = function(){
var expectedArgs = jasmine.util.argsToArray(arguments);
if (!jasmine.isSpy(this.actual)){
throw new Error('Expected a spy,but got ' + jasmine.pp(this.actual) + '.');
}
this.message = function(){
var invertedMessage = "Expected spy " + this.actual.identity + " not to have been called with " + jasmine.pp(expectedArgs) + " but it was.";
var positiveMessage = "";
if (this.actual.callCount === 0){
positiveMessage = "Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but it was never called.";
}
else{
positiveMessage = "Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but actual calls were " + jasmine.pp(this.actual.argsForCall).replace(/^\[ | \]$/g,'')}
return [positiveMessage,invertedMessage];
}
;
return this.env.contains_(this.actual.argsForCall,expectedArgs);
}
;
/** @deprecated Use expect(xxx).toHaveBeenCalledWith() instead */
jasmine.Matchers.prototype.wasCalledWith = jasmine.Matchers.prototype.toHaveBeenCalledWith;
/** @deprecated Use expect(xxx).not.toHaveBeenCalledWith() instead */
jasmine.Matchers.prototype.wasNotCalledWith = function(){
var expectedArgs = jasmine.util.argsToArray(arguments);
if (!jasmine.isSpy(this.actual)){
throw new Error('Expected a spy,but got ' + jasmine.pp(this.actual) + '.');
}
this.message = function(){
return [ "Expected spy not to have been called with " + jasmine.pp(expectedArgs) + " but it was","Expected spy to have been called with " + jasmine.pp(expectedArgs) + " but it was" ];
}
;
return !this.env.contains_(this.actual.argsForCall,expectedArgs);
}
;
/** * Matcher that checks that the expected item is an element in the actual Array. * * @param{
Object}
expected */
jasmine.Matchers.prototype.toContain = function(expected){
return this.env.contains_(this.actual,expected);
}
;
/** * Matcher that checks that the expected item is NOT an element in the actual Array. * * @param{
Object}
expected * @deprecated as of 1.0. Use not.toContain() instead. */
jasmine.Matchers.prototype.toNotContain = function(expected){
return !this.env.contains_(this.actual,expected);
}
;
jasmine.Matchers.prototype.toBeLessThan = function(expected){
return this.actual < expected;
}
;
jasmine.Matchers.prototype.toBeGreaterThan = function(expected){
return this.actual > expected;
}
;
/** * Matcher that checks that the expected item is equal to the actual item * up to a given level of decimal precision (default 2). * * @param{
Number}
expected * @param{
Number}
precision,as number of decimal places */
jasmine.Matchers.prototype.toBeCloseTo = function(expected,precision){
if (!(precision === 0)){
precision = precision || 2;
}
return Math.abs(expected - this.actual) < (Math.pow(10,-precision) / 2);
}
;
/** * Matcher that checks that the expected exception was thrown by the actual. * * @param{
String}
[expected] */
jasmine.Matchers.prototype.toThrow = function(expected){
var result = false;
var exception;
if (typeof this.actual != 'function'){
throw new Error('Actual is not a function');
}
try{
this.actual();
}
catch (e){
exception = e;
}
if (exception){
result = (expected === jasmine.undefined || this.env.equals_(exception.message || exception,expected.message || expected));
}
var not = this.isNot ? "not ":"";
this.message = function(){
if (exception && (expected === jasmine.undefined || !this.env.equals_(exception.message || exception,expected.message || expected))){
return ["Expected function " + not + "to throw",expected ? expected.message || expected:"an exception",",but it threw",exception.message || exception].join(' ');
}
else{
return "Expected function to throw an exception.";
}
}
;
return result;
}
;
jasmine.Matchers.Any = function(expectedClass){
this.expectedClass = expectedClass;
}
;
jasmine.Matchers.Any.prototype.jasmineMatches = function(other){
if (this.expectedClass == String){
return typeof other == 'string' || other instanceof String;
}
if (this.expectedClass == Number){
return typeof other == 'number' || other instanceof Number;
}
if (this.expectedClass == Function){
return typeof other == 'function' || other instanceof Function;
}
if (this.expectedClass == Object){
return typeof other == 'object';
}
return other instanceof this.expectedClass;
}
;
jasmine.Matchers.Any.prototype.jasmineToString = function(){
return '<jasmine.any(' + this.expectedClass + ')>';
}
;
jasmine.Matchers.ObjectContaining = function (sample){
this.sample = sample;
}
;
jasmine.Matchers.ObjectContaining.prototype.jasmineMatches = function(other,mismatchKeys,mismatchValues){
mismatchKeys = mismatchKeys || [];
mismatchValues = mismatchValues || [];
var env = jasmine.getEnv();
var hasKey = function(obj,keyName){
return obj != null && obj[keyName] !== jasmine.undefined;
}
;
for (var property in this.sample){
if (!hasKey(other,property) && hasKey(this.sample,property)){
mismatchKeys.push("expected has key '" + property + "',but missing from actual.");
}
else if (!env.equals_(this.sample[property],other[property],mismatchKeys,mismatchValues)){
mismatchValues.push("'" + property + "' was '" + (other[property] ? jasmine.util.htmlEscape(other[property].toString()):other[property]) + "' in expected,but was '" + (this.sample[property] ? jasmine.util.htmlEscape(this.sample[property].toString()):this.sample[property]) + "' in actual.");
}
}
return (mismatchKeys.length === 0 && mismatchValues.length === 0);
}
;
jasmine.Matchers.ObjectContaining.prototype.jasmineToString = function (){
return "<jasmine.objectContaining(" + jasmine.pp(this.sample) + ")>";
}
;
// Mock setTimeout,clearTimeout// Contributed by Pivotal Computer Systems,www.pivotalsf.comjasmine.FakeTimer = function(){
this.reset();
var self = this;
self.setTimeout = function(funcToCall,millis){
self.timeoutsMade++;
self.scheduleFunction(self.timeoutsMade,funcToCall,millis,false);
return self.timeoutsMade;
}
;
self.setInterval = function(funcToCall,millis){
self.timeoutsMade++;
self.scheduleFunction(self.timeoutsMade,funcToCall,millis,true);
return self.timeoutsMade;
}
;
self.clearTimeout = function(timeoutKey){
self.scheduledFunctions[timeoutKey] = jasmine.undefined;
}
;
self.clearInterval = function(timeoutKey){
self.scheduledFunctions[timeoutKey] = jasmine.undefined;
}
;
}
;
jasmine.FakeTimer.prototype.reset = function(){
this.timeoutsMade = 0;
this.scheduledFunctions ={
}
;
this.nowMillis = 0;
}
;
jasmine.FakeTimer.prototype.tick = function(millis){
var oldMillis = this.nowMillis;
var newMillis = oldMillis + millis;
this.runFunctionsWithinRange(oldMillis,newMillis);
this.nowMillis = newMillis;
}
;
jasmine.FakeTimer.prototype.runFunctionsWithinRange = function(oldMillis,nowMillis){
var scheduledFunc;
var funcsToRun = [];
for (var timeoutKey in this.scheduledFunctions){
scheduledFunc = this.scheduledFunctions[timeoutKey];
if (scheduledFunc != jasmine.undefined && scheduledFunc.runAtMillis >= oldMillis && scheduledFunc.runAtMillis <= nowMillis){
funcsToRun.push(scheduledFunc);
this.scheduledFunctions[timeoutKey] = jasmine.undefined;
}
}
if (funcsToRun.length > 0){
funcsToRun.sort(function(a,b){
return a.runAtMillis - b.runAtMillis;
}
);
for (var i = 0;
i < funcsToRun.length;
++i){
try{
var funcToRun = funcsToRun[i];
this.nowMillis = funcToRun.runAtMillis;
funcToRun.funcToCall();
if (funcToRun.recurring){
this.scheduleFunction(funcToRun.timeoutKey,funcToRun.funcToCall,funcToRun.millis,true);
}
}
catch(e){
}
}
this.runFunctionsWithinRange(oldMillis,nowMillis);
}
}
;
jasmine.FakeTimer.prototype.scheduleFunction = function(timeoutKey,funcToCall,millis,recurring){
this.scheduledFunctions[timeoutKey] ={
runAtMillis:this.nowMillis + millis,funcToCall:funcToCall,recurring:recurring,timeoutKey:timeoutKey,millis:millis}
;
}
;
/** * @namespace */
jasmine.Clock ={
defaultFakeTimer:new jasmine.FakeTimer(),reset:function(){
jasmine.Clock.assertInstalled();
jasmine.Clock.defaultFakeTimer.reset();
}
,tick:function(millis){
jasmine.Clock.assertInstalled();
jasmine.Clock.defaultFakeTimer.tick(millis);
}
,runFunctionsWithinRange:function(oldMillis,nowMillis){
jasmine.Clock.defaultFakeTimer.runFunctionsWithinRange(oldMillis,nowMillis);
}
,scheduleFunction:function(timeoutKey,funcToCall,millis,recurring){
jasmine.Clock.defaultFakeTimer.scheduleFunction(timeoutKey,funcToCall,millis,recurring);
}
,useMock:function(){
if (!jasmine.Clock.isInstalled()){
var spec = jasmine.getEnv().currentSpec;
spec.after(jasmine.Clock.uninstallMock);
jasmine.Clock.installMock();
}
}
,installMock:function(){
jasmine.Clock.installed = jasmine.Clock.defaultFakeTimer;
}
,uninstallMock:function(){
jasmine.Clock.assertInstalled();
jasmine.Clock.installed = jasmine.Clock.real;
}
,real:{
setTimeout:jasmine.getGlobal().setTimeout,clearTimeout:jasmine.getGlobal().clearTimeout,setInterval:jasmine.getGlobal().setInterval,clearInterval:jasmine.getGlobal().clearInterval}
,assertInstalled:function(){
if (!jasmine.Clock.isInstalled()){
throw new Error("Mock clock is not installed,use jasmine.Clock.useMock()");
}
}
,isInstalled:function(){
return jasmine.Clock.installed == jasmine.Clock.defaultFakeTimer;
}
,installed:null}
;
jasmine.Clock.installed = jasmine.Clock.real;
//else for IE supportjasmine.getGlobal().setTimeout = function(funcToCall,millis){
if (jasmine.Clock.installed.setTimeout.apply){
return jasmine.Clock.installed.setTimeout.apply(this,arguments);
}
else{
return jasmine.Clock.installed.setTimeout(funcToCall,millis);
}
}
;
jasmine.getGlobal().setInterval = function(funcToCall,millis){
if (jasmine.Clock.installed.setInterval.apply){
return jasmine.Clock.installed.setInterval.apply(this,arguments);
}
else{
return jasmine.Clock.installed.setInterval(funcToCall,millis);
}
}
;
jasmine.getGlobal().clearTimeout = function(timeoutKey){
if (jasmine.Clock.installed.clearTimeout.apply){
return jasmine.Clock.installed.clearTimeout.apply(this,arguments);
}
else{
return jasmine.Clock.installed.clearTimeout(timeoutKey);
}
}
;
jasmine.getGlobal().clearInterval = function(timeoutKey){
if (jasmine.Clock.installed.clearTimeout.apply){
return jasmine.Clock.installed.clearInterval.apply(this,arguments);
}
else{
return jasmine.Clock.installed.clearInterval(timeoutKey);
}
}
;
/** * @constructor */
jasmine.MultiReporter = function(){
this.subReporters_ = [];
}
;
jasmine.util.inherit(jasmine.MultiReporter,jasmine.Reporter);
jasmine.MultiReporter.prototype.addReporter = function(reporter){
this.subReporters_.push(reporter);
}
;
(function(){
var functionNames = [ "reportRunnerStarting","reportRunnerResults","reportSuiteResults","reportSpecStarting","reportSpecResults","log" ];
for (var i = 0;
i < functionNames.length;
i++){
var functionName = functionNames[i];
jasmine.MultiReporter.prototype[functionName] = (function(functionName){
return function(){
for (var j = 0;
j < this.subReporters_.length;
j++){
var subReporter = this.subReporters_[j];
if (subReporter[functionName]){
subReporter[functionName].apply(subReporter,arguments);
}
}
}
;
}
)(functionName);
}
}
)();
/** * Holds results for a set of Jasmine spec. Allows for the results array to hold another jasmine.NestedResults * * @constructor */
jasmine.NestedResults = function(){
/** * The total count of results */
this.totalCount = 0;
/** * Number of passed results */
this.passedCount = 0;
/** * Number of failed results */
this.failedCount = 0;
/** * Was this suite/spec skipped? */
this.skipped = false;
/** * @ignore */
this.items_ = [];
}
;
/** * Roll up the result counts. * * @param result */
jasmine.NestedResults.prototype.rollupCounts = function(result){
this.totalCount += result.totalCount;
this.passedCount += result.passedCount;
this.failedCount += result.failedCount;
}
;
/** * Adds a log message. * @param values Array of message parts which will be concatenated later. */
jasmine.NestedResults.prototype.log = function(values){
this.items_.push(new jasmine.MessageResult(values));
}
;
/** * Getter for the results:message & results. */
jasmine.NestedResults.prototype.getItems = function(){
return this.items_;
}
;
/** * Adds a result,tracking counts (total,passed,& failed) * @param{
jasmine.ExpectationResult|jasmine.NestedResults}
result */
jasmine.NestedResults.prototype.addResult = function(result){
if (result.type != 'log'){
if (result.items_){
this.rollupCounts(result);
}
else{
this.totalCount++;
if (result.passed()){
this.passedCount++;
}
else{
this.failedCount++;
}
}
}
this.items_.push(result);
}
;
/** * @returns{
Boolean}
True if <b>everything</b> below passed */
jasmine.NestedResults.prototype.passed = function(){
return this.passedCount === this.totalCount;
}
;
/** * Base class for pretty printing for expectation results. */
jasmine.PrettyPrinter = function(){
this.ppNestLevel_ = 0;
}
;
/** * Formats a value in a nice,human-readable string. * * @param value */
jasmine.PrettyPrinter.prototype.format = function(value){
this.ppNestLevel_++;
try{
if (value === jasmine.undefined){
this.emitScalar('undefined');
}
else if (value === null){
this.emitScalar('null');
}
else if (value === jasmine.getGlobal()){
this.emitScalar('<global>');
}
else if (value.jasmineToString){
this.emitScalar(value.jasmineToString());
}
else if (typeof value === 'string'){
this.emitString(value);
}
else if (jasmine.isSpy(value)){
this.emitScalar("spy on " + value.identity);
}
else if (value instanceof RegExp){
this.emitScalar(value.toString());
}
else if (typeof value === 'function'){
this.emitScalar('Function');
}
else if (typeof value.nodeType === 'number'){
this.emitScalar('HTMLNode');
}
else if (value instanceof Date){
this.emitScalar('Date(' + value + ')');
}
else if (value.__Jasmine_been_here_before__){
this.emitScalar('<circular reference:' + (jasmine.isArray_(value) ? 'Array':'Object') + '>');
}
else if (jasmine.isArray_(value) || typeof value == 'object'){
value.__Jasmine_been_here_before__ = true;
if (jasmine.isArray_(value)){
this.emitArray(value);
}
else{
this.emitObject(value);
}
delete value.__Jasmine_been_here_before__;
}
else{
this.emitScalar(value.toString());
}
}
finally{
this.ppNestLevel_--;
}
}
;
jasmine.PrettyPrinter.prototype.iterateObject = function(obj,fn){
for (var property in obj){
if (!obj.hasOwnProperty(property)) continue;
if (property == '__Jasmine_been_here_before__') continue;
fn(property,obj.__lookupGetter__ ? (obj.__lookupGetter__(property) !== jasmine.undefined && obj.__lookupGetter__(property) !== null):false);
}
}
;
jasmine.PrettyPrinter.prototype.emitArray = jasmine.unimplementedMethod_;
jasmine.PrettyPrinter.prototype.emitObject = jasmine.unimplementedMethod_;
jasmine.PrettyPrinter.prototype.emitScalar = jasmine.unimplementedMethod_;
jasmine.PrettyPrinter.prototype.emitString = jasmine.unimplementedMethod_;
jasmine.StringPrettyPrinter = function(){
jasmine.PrettyPrinter.call(this);
this.string = '';
}
;
jasmine.util.inherit(jasmine.StringPrettyPrinter,jasmine.PrettyPrinter);
jasmine.StringPrettyPrinter.prototype.emitScalar = function(value){
this.append(value);
}
;
jasmine.StringPrettyPrinter.prototype.emitString = function(value){
this.append("'" + value + "'");
}
;
jasmine.StringPrettyPrinter.prototype.emitArray = function(array){
if (this.ppNestLevel_ > jasmine.MAX_PRETTY_PRINT_DEPTH){
this.append("Array");
return;
}
this.append('[ ');
for (var i = 0;
i < array.length;
i++){
if (i > 0){
this.append(',');
}
this.format(array[i]);
}
this.append(' ]');
}
;
jasmine.StringPrettyPrinter.prototype.emitObject = function(obj){
if (this.ppNestLevel_ > jasmine.MAX_PRETTY_PRINT_DEPTH){
this.append("Object");
return;
}
var self = this;
this.append('{
');
var first = true;
this.iterateObject(obj,function(property,isGetter){
if (first){
first = false;
}
else{
self.append(',');
}
self.append(property);
self.append(':');
if (isGetter){
self.append('<getter>');
}
else{
self.format(obj[property]);
}
}
);
this.append('}
');
}
;
jasmine.StringPrettyPrinter.prototype.append = function(value){
this.string += value;
}
;
jasmine.Queue = function(env){
this.env = env;
// parallel to blocks. each true value in this array means the block will // get executed even if we abort this.ensured = [];
this.blocks = [];
this.running = false;
this.index = 0;
this.offset = 0;
this.abort = false;
}
;
jasmine.Queue.prototype.addBefore = function(block,ensure){
if (ensure === jasmine.undefined){
ensure = false;
}
this.blocks.unshift(block);
this.ensured.unshift(ensure);
}
;
jasmine.Queue.prototype.add = function(block,ensure){
if (ensure === jasmine.undefined){
ensure = false;
}
this.blocks.push(block);
this.ensured.push(ensure);
}
;
jasmine.Queue.prototype.insertNext = function(block,ensure){
if (ensure === jasmine.undefined){
ensure = false;
}
this.ensured.splice((this.index + this.offset + 1),0,ensure);
this.blocks.splice((this.index + this.offset + 1),0,block);
this.offset++;
}
;
jasmine.Queue.prototype.start = function(onComplete){
this.running = true;
this.onComplete = onComplete;
this.next_();
}
;
jasmine.Queue.prototype.isRunning = function(){
return this.running;
}
;
jasmine.Queue.LOOP_DONT_RECURSE = true;
jasmine.Queue.prototype.next_ = function(){
var self = this;
var goAgain = true;
while (goAgain){
goAgain = false;
if (self.index < self.blocks.length && !(this.abort && !this.ensured[self.index])){
var calledSynchronously = true;
var completedSynchronously = false;
var onComplete = function (){
if (jasmine.Queue.LOOP_DONT_RECURSE && calledSynchronously){
completedSynchronously = true;
return;
}
if (self.blocks[self.index].abort){
self.abort = true;
}
self.offset = 0;
self.index++;
var now = new Date().getTime();
if (self.env.updateInterval && now - self.env.lastUpdate > self.env.updateInterval){
self.env.lastUpdate = now;
self.env.setTimeout(function(){
self.next_();
}
,0);
}
else{
if (jasmine.Queue.LOOP_DONT_RECURSE && completedSynchronously){
goAgain = true;
}
else{
self.next_();
}
}
}
;
self.blocks[self.index].execute(onComplete);
calledSynchronously = false;
if (completedSynchronously){
onComplete();
}
}
else{
self.running = false;
if (self.onComplete){
self.onComplete();
}
}
}
}
;
jasmine.Queue.prototype.results = function(){
var results = new jasmine.NestedResults();
for (var i = 0;
i < this.blocks.length;
i++){
if (this.blocks[i].results){
results.addResult(this.blocks[i].results());
}
}
return results;
}
;
/** * Runner * * @constructor * @param{
jasmine.Env}
env */
jasmine.Runner = function(env){
var self = this;
self.env = env;
self.queue = new jasmine.Queue(env);
self.before_ = [];
self.after_ = [];
self.suites_ = [];
}
;
jasmine.Runner.prototype.execute = function(){
var self = this;
if (self.env.reporter.reportRunnerStarting){
self.env.reporter.reportRunnerStarting(this);
}
self.queue.start(function (){
self.finishCallback();
}
);
}
;
jasmine.Runner.prototype.beforeEach = function(beforeEachFunction){
beforeEachFunction.typeName = 'beforeEach';
this.before_.splice(0,0,beforeEachFunction);
}
;
jasmine.Runner.prototype.afterEach = function(afterEachFunction){
afterEachFunction.typeName = 'afterEach';
this.after_.splice(0,0,afterEachFunction);
}
;
jasmine.Runner.prototype.finishCallback = function(){
this.env.reporter.reportRunnerResults(this);
}
;
jasmine.Runner.prototype.addSuite = function(suite){
this.suites_.push(suite);
}
;
jasmine.Runner.prototype.add = function(block){
if (block instanceof jasmine.Suite){
this.addSuite(block);
}
this.queue.add(block);
}
;
jasmine.Runner.prototype.specs = function (){
var suites = this.suites();
var specs = [];
for (var i = 0;
i < suites.length;
i++){
specs = specs.concat(suites[i].specs());
}
return specs;
}
;
jasmine.Runner.prototype.suites = function(){
return this.suites_;
}
;
jasmine.Runner.prototype.topLevelSuites = function(){
var topLevelSuites = [];
for (var i = 0;
i < this.suites_.length;
i++){
if (!this.suites_[i].parentSuite){
topLevelSuites.push(this.suites_[i]);
}
}
return topLevelSuites;
}
;
jasmine.Runner.prototype.results = function(){
return this.queue.results();
}
;
/** * Internal representation of a Jasmine specification,or test. * * @constructor * @param{
jasmine.Env}
env * @param{
jasmine.Suite}
suite * @param{
String}
description */
jasmine.Spec = function(env,suite,description){
if (!env){
throw new Error('jasmine.Env() required');
}
if (!suite){
throw new Error('jasmine.Suite() required');
}
var spec = this;
spec.id = env.nextSpecId ? env.nextSpecId():null;
spec.env = env;
spec.suite = suite;
spec.description = description;
spec.queue = new jasmine.Queue(env);
spec.afterCallbacks = [];
spec.spies_ = [];
spec.results_ = new jasmine.NestedResults();
spec.results_.description = description;
spec.matchersClass = null;
}
;
jasmine.Spec.prototype.getFullName = function(){
return this.suite.getFullName() + ' ' + this.description + '.';
}
;
jasmine.Spec.prototype.results = function(){
return this.results_;
}
;
/** * All parameters are pretty-printed and concatenated together,then written to the spec's output. * * Be careful not to leave calls to <code>jasmine.log</code> in production code. */
jasmine.Spec.prototype.log = function(){
return this.results_.log(arguments);
}
;
jasmine.Spec.prototype.runs = function (func){
var block = new jasmine.Block(this.env,func,this);
this.addToQueue(block);
return this;
}
;
jasmine.Spec.prototype.addToQueue = function (block){
if (this.queue.isRunning()){
this.queue.insertNext(block);
}
else{
this.queue.add(block);
}
}
;
/** * @param{
jasmine.ExpectationResult}
result */
jasmine.Spec.prototype.addMatcherResult = function(result){
this.results_.addResult(result);
}
;
jasmine.Spec.prototype.expect = function(actual){
var positive = new (this.getMatchersClass_())(this.env,actual,this);
positive.not = new (this.getMatchersClass_())(this.env,actual,this,true);
return positive;
}
;
/** * Waits a fixed time period before moving to the next block. * * @deprecated Use waitsFor() instead * @param{
Number}
timeout milliseconds to wait */
jasmine.Spec.prototype.waits = function(timeout){
var waitsFunc = new jasmine.WaitsBlock(this.env,timeout,this);
this.addToQueue(waitsFunc);
return this;
}
;
/** * Waits for the latchFunction to return true before proceeding to the next block. * * @param{
Function}
latchFunction * @param{
String}
optional_timeoutMessage * @param{
Number}
optional_timeout */
jasmine.Spec.prototype.waitsFor = function(latchFunction,optional_timeoutMessage,optional_timeout){
var latchFunction_ = null;
var optional_timeoutMessage_ = null;
var optional_timeout_ = null;
for (var i = 0;
i < arguments.length;
i++){
var arg = arguments[i];
switch (typeof arg){
case 'function':latchFunction_ = arg;
break;
case 'string':optional_timeoutMessage_ = arg;
break;
case 'number':optional_timeout_ = arg;
break;
}
}
var waitsForFunc = new jasmine.WaitsForBlock(this.env,optional_timeout_,latchFunction_,optional_timeoutMessage_,this);
this.addToQueue(waitsForFunc);
return this;
}
;
jasmine.Spec.prototype.fail = function (e){
var expectationResult = new jasmine.ExpectationResult({
passed:false,message:e ? jasmine.util.formatException(e):'Exception',trace:{
stack:e.stack}
}
);
this.results_.addResult(expectationResult);
}
;
jasmine.Spec.prototype.getMatchersClass_ = function(){
return this.matchersClass || this.env.matchersClass;
}
;
jasmine.Spec.prototype.addMatchers = function(matchersPrototype){
var parent = this.getMatchersClass_();
var newMatchersClass = function(){
parent.apply(this,arguments);
}
;
jasmine.util.inherit(newMatchersClass,parent);
jasmine.Matchers.wrapInto_(matchersPrototype,newMatchersClass);
this.matchersClass = newMatchersClass;
}
;
jasmine.Spec.prototype.finishCallback = function(){
this.env.reporter.reportSpecResults(this);
}
;
jasmine.Spec.prototype.finish = function(onComplete){
this.removeAllSpies();
this.finishCallback();
if (onComplete){
onComplete();
}
}
;
jasmine.Spec.prototype.after = function(doAfter){
if (this.queue.isRunning()){
this.queue.add(new jasmine.Block(this.env,doAfter,this),true);
}
else{
this.afterCallbacks.unshift(doAfter);
}
}
;
jasmine.Spec.prototype.execute = function(onComplete){
var spec = this;
if (!spec.env.specFilter(spec)){
spec.results_.skipped = true;
spec.finish(onComplete);
return;
}
this.env.reporter.reportSpecStarting(this);
spec.env.currentSpec = spec;
spec.addBeforesAndAftersToQueue();
spec.queue.start(function (){
spec.finish(onComplete);
}
);
}
;
jasmine.Spec.prototype.addBeforesAndAftersToQueue = function(){
var runner = this.env.currentRunner();
var i;
for (var suite = this.suite;
suite;
suite = suite.parentSuite){
for (i = 0;
i < suite.before_.length;
i++){
this.queue.addBefore(new jasmine.Block(this.env,suite.before_[i],this));
}
}
for (i = 0;
i < runner.before_.length;
i++){
this.queue.addBefore(new jasmine.Block(this.env,runner.before_[i],this));
}
for (i = 0;
i < this.afterCallbacks.length;
i++){
this.queue.add(new jasmine.Block(this.env,this.afterCallbacks[i],this),true);
}
for (suite = this.suite;
suite;
suite = suite.parentSuite){
for (i = 0;
i < suite.after_.length;
i++){
this.queue.add(new jasmine.Block(this.env,suite.after_[i],this),true);
}
}
for (i = 0;
i < runner.after_.length;
i++){
this.queue.add(new jasmine.Block(this.env,runner.after_[i],this),true);
}
}
;
jasmine.Spec.prototype.explodes = function(){
throw 'explodes function should not have been called';
}
;
jasmine.Spec.prototype.spyOn = function(obj,methodName,ignoreMethodDoesntExist){
if (obj == jasmine.undefined){
throw "spyOn could not find an object to spy upon for " + methodName + "()";
}
if (!ignoreMethodDoesntExist && obj[methodName] === jasmine.undefined){
throw methodName + '() method does not exist';
}
if (!ignoreMethodDoesntExist && obj[methodName] && obj[methodName].isSpy){
throw new Error(methodName + ' has already been spied upon');
}
var spyObj = jasmine.createSpy(methodName);
this.spies_.push(spyObj);
spyObj.baseObj = obj;
spyObj.methodName = methodName;
spyObj.originalValue = obj[methodName];
obj[methodName] = spyObj;
return spyObj;
}
;
jasmine.Spec.prototype.removeAllSpies = function(){
for (var i = 0;
i < this.spies_.length;
i++){
var spy = this.spies_[i];
spy.baseObj[spy.methodName] = spy.originalValue;
}
this.spies_ = [];
}
;
/** * Internal representation of a Jasmine suite. * * @constructor * @param{
jasmine.Env}
env * @param{
String}
description * @param{
Function}
specDefinitions * @param{
jasmine.Suite}
parentSuite */
jasmine.Suite = function(env,description,specDefinitions,parentSuite){
var self = this;
self.id = env.nextSuiteId ? env.nextSuiteId():null;
self.description = description;
self.queue = new jasmine.Queue(env);
self.parentSuite = parentSuite;
self.env = env;
self.before_ = [];
self.after_ = [];
self.children_ = [];
self.suites_ = [];
self.specs_ = [];
}
;
jasmine.Suite.prototype.getFullName = function(){
var fullName = this.description;
for (var parentSuite = this.parentSuite;
parentSuite;
parentSuite = parentSuite.parentSuite){
fullName = parentSuite.description + ' ' + fullName;
}
return fullName;
}
;
jasmine.Suite.prototype.finish = function(onComplete){
this.env.reporter.reportSuiteResults(this);
this.finished = true;
if (typeof(onComplete) == 'function'){
onComplete();
}
}
;
jasmine.Suite.prototype.beforeEach = function(beforeEachFunction){
beforeEachFunction.typeName = 'beforeEach';
this.before_.unshift(beforeEachFunction);
}
;
jasmine.Suite.prototype.afterEach = function(afterEachFunction){
afterEachFunction.typeName = 'afterEach';
this.after_.unshift(afterEachFunction);
}
;
jasmine.Suite.prototype.results = function(){
return this.queue.results();
}
;
jasmine.Suite.prototype.add = function(suiteOrSpec){
this.children_.push(suiteOrSpec);
if (suiteOrSpec instanceof jasmine.Suite){
this.suites_.push(suiteOrSpec);
this.env.currentRunner().addSuite(suiteOrSpec);
}
else{
this.specs_.push(suiteOrSpec);
}
this.queue.add(suiteOrSpec);
}
;
jasmine.Suite.prototype.specs = function(){
return this.specs_;
}
;
jasmine.Suite.prototype.suites = function(){
return this.suites_;
}
;
jasmine.Suite.prototype.children = function(){
return this.children_;
}
;
jasmine.Suite.prototype.execute = function(onComplete){
var self = this;
this.queue.start(function (){
self.finish(onComplete);
}
);
}
;
jasmine.WaitsBlock = function(env,timeout,spec){
this.timeout = timeout;
jasmine.Block.call(this,env,null,spec);
}
;
jasmine.util.inherit(jasmine.WaitsBlock,jasmine.Block);
jasmine.WaitsBlock.prototype.execute = function (onComplete){
if (jasmine.VERBOSE){
this.env.reporter.log('>> Jasmine waiting for ' + this.timeout + ' ms...');
}
this.env.setTimeout(function (){
onComplete();
}
,this.timeout);
}
;
/** * A block which waits for some condition to become true,with timeout. * * @constructor * @extends jasmine.Block * @param{
jasmine.Env}
env The Jasmine environment. * @param{
Number}
timeout The maximum time in milliseconds to wait for the condition to become true. * @param{
Function}
latchFunction A function which returns true when the desired condition has been met. * @param{
String}
message The message to display if the desired condition hasn't been met within the given time period. * @param{
jasmine.Spec}
spec The Jasmine spec. */
jasmine.WaitsForBlock = function(env,timeout,latchFunction,message,spec){
this.timeout = timeout || env.defaultTimeoutInterval;
this.latchFunction = latchFunction;
this.message = message;
this.totalTimeSpentWaitingForLatch = 0;
jasmine.Block.call(this,env,null,spec);
}
;
jasmine.util.inherit(jasmine.WaitsForBlock,jasmine.Block);
jasmine.WaitsForBlock.TIMEOUT_INCREMENT = 10;
jasmine.WaitsForBlock.prototype.execute = function(onComplete){
if (jasmine.VERBOSE){
this.env.reporter.log('>> Jasmine waiting for ' + (this.message || 'something to happen'));
}
var latchFunctionResult;
try{
latchFunctionResult = this.latchFunction.apply(this.spec);
}
catch (e){
this.spec.fail(e);
onComplete();
return;
}
if (latchFunctionResult){
onComplete();
}
else if (this.totalTimeSpentWaitingForLatch >= this.timeout){
var message = 'timed out after ' + this.timeout + ' msec waiting for ' + (this.message || 'something to happen');
this.spec.fail({
name:'timeout',message:message}
);
this.abort = true;
onComplete();
}
else{
this.totalTimeSpentWaitingForLatch += jasmine.WaitsForBlock.TIMEOUT_INCREMENT;
var self = this;
this.env.setTimeout(function(){
self.execute(onComplete);
}
,jasmine.WaitsForBlock.TIMEOUT_INCREMENT);
}
}
;
jasmine.version_={
"major":1,"minor":3,"build":1,"revision":1354556913}
;
CSS代码(dragdealer.css):
/** * Dragdealer.js 0.9.8 * http://github.com/skidding/dragdealer * * (c) 2010+ Ovidiu Cherecheș * http://skidding.mit-license.org */
.dragdealer{position:relative;height:30px;background:#EEE;}
.dragdealer .handle{position:absolute;top:0;left:0;cursor:pointer;}
.dragdealer .red-bar{width:100px;height:30px;background:#CC0000;color:#FFF;font-size:14px;line-height:30px;text-align:center;}
.dragdealer .disabled{background:#898989;}
CSS代码(jasmine.css):
body{background-color:#eeeeee;padding:0;margin:5px;overflow-y:scroll;}
#HTMLReporter{font-size:11px;font-family:Monaco,"Lucida Console",monospace;line-height:14px;color:#333333;}
#HTMLReporter a{text-decoration:none;}
#HTMLReporter a:hover{text-decoration:underline;}
#HTMLReporter p,#HTMLReporter h1,#HTMLReporter h2,#HTMLReporter h3,#HTMLReporter h4,#HTMLReporter h5,#HTMLReporter h6{margin:0;line-height:14px;}
#HTMLReporter .banner,#HTMLReporter .symbolSummary,#HTMLReporter .summary,#HTMLReporter .resultMessage,#HTMLReporter .specDetail .description,#HTMLReporter .alert .bar,#HTMLReporter .stackTrace{padding-left:9px;padding-right:9px;}
#HTMLReporter #jasmine_content{position:fixed;right:100%;}
#HTMLReporter .version{color:#aaaaaa;}
#HTMLReporter .banner{margin-top:14px;}
#HTMLReporter .duration{color:#aaaaaa;float:right;}
#HTMLReporter .symbolSummary{overflow:hidden;*zoom:1;margin:14px 0;}
#HTMLReporter .symbolSummary li{display:block;float:left;height:7px;width:14px;margin-bottom:7px;font-size:16px;}
#HTMLReporter .symbolSummary li.passed{font-size:14px;}
#HTMLReporter .symbolSummary li.passed:before{color:#5e7d00;content:"\02022";}
#HTMLReporter .symbolSummary li.failed{line-height:9px;}
#HTMLReporter .symbolSummary li.failed:before{color:#b03911;content:"x";font-weight:bold;margin-left:-1px;}
#HTMLReporter .symbolSummary li.skipped{font-size:14px;}
#HTMLReporter .symbolSummary li.skipped:before{color:#bababa;content:"\02022";}
#HTMLReporter .symbolSummary li.pending{line-height:11px;}
#HTMLReporter .symbolSummary li.pending:before{color:#aaaaaa;content:"-";}
#HTMLReporter .exceptions{color:#fff;float:right;margin-top:5px;margin-right:5px;}
#HTMLReporter .bar{line-height:28px;font-size:14px;display:block;color:#eee;}
#HTMLReporter .runningAlert{background-color:#666666;}
#HTMLReporter .skippedAlert{background-color:#aaaaaa;}
#HTMLReporter .skippedAlert:first-child{background-color:#333333;}
#HTMLReporter .skippedAlert:hover{text-decoration:none;color:white;text-decoration:underline;}
#HTMLReporter .passingAlert{background-color:#a6b779;}
#HTMLReporter .passingAlert:first-child{background-color:#5e7d00;}
#HTMLReporter .failingAlert{background-color:#cf867e;}
#HTMLReporter .failingAlert:first-child{background-color:#b03911;}
#HTMLReporter .results{margin-top:14px;}
#HTMLReporter #details{display:none;}
#HTMLReporter .resultsMenu,#HTMLReporter .resultsMenu a{background-color:#fff;color:#333333;}
#HTMLReporter.showDetails .summaryMenuItem{font-weight:normal;text-decoration:inherit;}
#HTMLReporter.showDetails .summaryMenuItem:hover{text-decoration:underline;}
#HTMLReporter.showDetails .detailsMenuItem{font-weight:bold;text-decoration:underline;}
#HTMLReporter.showDetails .summary{display:none;}
#HTMLReporter.showDetails #details{display:block;}
#HTMLReporter .summaryMenuItem{font-weight:bold;text-decoration:underline;}
#HTMLReporter .summary{margin-top:14px;}
#HTMLReporter .summary .suite .suite,#HTMLReporter .summary .specSummary{margin-left:14px;}
#HTMLReporter .summary .specSummary.passed a{color:#5e7d00;}
#HTMLReporter .summary .specSummary.failed a{color:#b03911;}
#HTMLReporter .description + .suite{margin-top:0;}
#HTMLReporter .suite{margin-top:14px;}
#HTMLReporter .suite a{color:#333333;}
#HTMLReporter #details .specDetail{margin-bottom:28px;}
#HTMLReporter #details .specDetail .description{display:block;color:white;background-color:#b03911;}
#HTMLReporter .resultMessage{padding-top:14px;color:#333333;}
#HTMLReporter .resultMessage span.result{display:block;}
#HTMLReporter .stackTrace{margin:5px 0 0 0;max-height:224px;overflow:auto;line-height:18px;color:#666666;border:1px solid #ddd;background:white;white-space:pre;}
#TrivialReporter{padding:8px 13px;position:absolute;top:0;bottom:0;left:0;right:0;overflow-y:scroll;background-color:white;font-family:"Helvetica Neue Light","Lucida Grande","Calibri","Arial",sans-serif;/*.resultMessage{*/
/*white-space:pre;*/
/*}
*/
}
#TrivialReporter a:visited,#TrivialReporter a{color:#303;}
#TrivialReporter a:hover,#TrivialReporter a:active{color:blue;}
#TrivialReporter .run_spec{float:right;padding-right:5px;font-size:.8em;text-decoration:none;}
#TrivialReporter .banner{color:#303;background-color:#fef;padding:5px;}
#TrivialReporter .logo{float:left;font-size:1.1em;padding-left:5px;}
#TrivialReporter .logo .version{font-size:.6em;padding-left:1em;}
#TrivialReporter .runner.running{background-color:yellow;}
#TrivialReporter .options{text-align:right;font-size:.8em;}
#TrivialReporter .suite{border:1px outset gray;margin:5px 0;padding-left:1em;}
#TrivialReporter .suite .suite{margin:5px;}
#TrivialReporter .suite.passed{background-color:#dfd;}
#TrivialReporter .suite.failed{background-color:#fdd;}
#TrivialReporter .spec{margin:5px;padding-left:1em;clear:both;}
#TrivialReporter .spec.failed,#TrivialReporter .spec.passed,#TrivialReporter .spec.skipped{padding-bottom:5px;border:1px solid gray;}
#TrivialReporter .spec.failed{background-color:#fbb;border-color:red;}
#TrivialReporter .spec.passed{background-color:#bfb;border-color:green;}
#TrivialReporter .spec.skipped{background-color:#bbb;}
#TrivialReporter .messages{border-left:1px dashed gray;padding-left:1em;padding-right:1em;}
#TrivialReporter .passed{background-color:#cfc;display:none;}
#TrivialReporter .failed{background-color:#fbb;}
#TrivialReporter .skipped{color:#777;background-color:#eee;display:none;}
#TrivialReporter .resultMessage span.result{display:block;line-height:2em;color:black;}
#TrivialReporter .resultMessage .mismatch{color:black;}
#TrivialReporter .stackTrace{white-space:pre;font-size:.8em;margin-left:10px;max-height:5em;overflow:auto;border:1px inset red;padding:1em;background:#eef;}
#TrivialReporter .finished-at{padding-left:1em;font-size:.6em;}
#TrivialReporter.show-passed .passed,#TrivialReporter.show-skipped .skipped{display:block;}
#TrivialReporter #jasmine_content{position:fixed;right:100%;}
#TrivialReporter .runner{border:1px solid gray;display:block;margin:5px 0;padding:2px 0 2px 10px;}