2012-06-30 18:13:02 +08:00
var isCommonJS = typeof window == "undefined" ;
2010-09-02 18:45:04 +08:00
/ * *
* Top level namespace for Jasmine , a lightweight JavaScript BDD / spec / testing framework .
*
* @ namespace
* /
var jasmine = { } ;
2012-06-30 18:13:02 +08:00
if ( isCommonJS ) exports . jasmine = jasmine ;
2010-09-02 18:45:04 +08:00
/ * *
* @ private
* /
jasmine . unimplementedMethod _ = function ( ) {
throw new Error ( "unimplemented method" ) ;
} ;
/ * *
* Use < code > jasmine . undefined < / c o d e > i n s t e a d o f < c o d e > u n d e f i n e d < / c o d e > , s i n c e < c o d e > u n d e f i n e d < / c o d e > i s j u s t
* a plain old variable and may be redefined by somebody else .
*
* @ private
* /
jasmine . undefined = jasmine . _ _ _undefined _ _ _ ;
2012-06-30 18:13:02 +08:00
/ * *
* Show diagnostic messages in the console if set to true
*
* /
jasmine . VERBOSE = false ;
2010-09-02 18:45:04 +08:00
/ * *
* 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 = "" ;
2012-06-30 18:13:02 +08:00
for ( var i = 0 ; i < this . values . length ; i ++ ) {
2010-09-02 18:45:04 +08:00
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 ;
2012-06-30 18:13:02 +08:00
var trace = ( params . trace || new Error ( this . message ) ) ;
this . trace = this . passed _ ? '' : trace ;
2010-09-02 18:45:04 +08:00
} ;
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 ( ) {
2012-06-30 18:13:02 +08:00
var env = jasmine . currentEnv _ = jasmine . currentEnv _ || new jasmine . Env ( ) ;
return env ;
2010-09-02 18:45:04 +08:00
} ;
/ * *
* @ ignore
* @ private
* @ param value
* @ returns { Boolean }
* /
jasmine . isArray _ = function ( value ) {
2012-06-30 18:13:02 +08:00
return jasmine . isA _ ( "Array" , value ) ;
2010-09-02 18:45:04 +08:00
} ;
/ * *
* @ 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 ) {
2012-06-30 18:13:02 +08:00
return obj . nodeType > 0 ;
2010-09-02 18:45:04 +08:00
} ;
/ * *
* 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 ) ;
} ;
2012-06-30 18:13:02 +08:00
/ * *
* 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 ) ;
} ;
2010-09-02 18:45:04 +08:00
/ * *
* 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 > c a l l n e w j a s m i n e . S p y ( ) d i r e c t l y - a s p y m u s t b e c r e a t e d u s i n g s p y O n , j a s m i n e . c r e a t e S p y o r j a s m i n e . c r e a t e S p y O b j .
*
* @ 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 ) {
2012-06-30 18:13:02 +08:00
if ( ! jasmine . isArray _ ( methodNames ) || methodNames . length === 0 ) {
2010-09-02 18:45:04 +08:00
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 < / c o d e > i n p r o d u c t i o n c o d e .
* /
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
* @ returns a Jasmine spy that can be chained with all spy methods
* /
var spyOn = function ( obj , methodName ) {
return jasmine . getEnv ( ) . currentSpec . spyOn ( obj , methodName ) ;
} ;
2012-06-30 18:13:02 +08:00
if ( isCommonJS ) exports . spyOn = spyOn ;
2010-09-02 18:45:04 +08:00
/ * *
* 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 ) ;
} ;
2012-06-30 18:13:02 +08:00
if ( isCommonJS ) exports . it = it ;
2010-09-02 18:45:04 +08:00
/ * *
* Creates a < em > disabled < / e m > J a s m i n e s p e c .
*
* 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 ) ;
} ;
2012-06-30 18:13:02 +08:00
if ( isCommonJS ) exports . xit = xit ;
2010-09-02 18:45:04 +08:00
/ * *
* 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
* /
var expect = function ( actual ) {
return jasmine . getEnv ( ) . currentSpec . expect ( actual ) ;
} ;
2012-06-30 18:13:02 +08:00
if ( isCommonJS ) exports . expect = expect ;
2010-09-02 18:45:04 +08:00
/ * *
* 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 ) ;
} ;
2012-06-30 18:13:02 +08:00
if ( isCommonJS ) exports . runs = runs ;
2010-09-02 18:45:04 +08:00
/ * *
* 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 ) ;
} ;
2012-06-30 18:13:02 +08:00
if ( isCommonJS ) exports . waits = waits ;
2010-09-02 18:45:04 +08:00
/ * *
* 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 ) ;
} ;
2012-06-30 18:13:02 +08:00
if ( isCommonJS ) exports . waitsFor = waitsFor ;
2010-09-02 18:45:04 +08:00
/ * *
* 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 ) ;
} ;
2012-06-30 18:13:02 +08:00
if ( isCommonJS ) exports . beforeEach = beforeEach ;
2010-09-02 18:45:04 +08:00
/ * *
* 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 ) ;
} ;
2012-06-30 18:13:02 +08:00
if ( isCommonJS ) exports . afterEach = afterEach ;
2010-09-02 18:45:04 +08:00
/ * *
* 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 ) ;
} ;
2012-06-30 18:13:02 +08:00
if ( isCommonJS ) exports . describe = describe ;
2010-09-02 18:45:04 +08:00
/ * *
* 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 ) ;
} ;
2012-06-30 18:13:02 +08:00
if ( isCommonJS ) exports . xdescribe = xdescribe ;
2010-09-02 18:45:04 +08:00
// Provide the XMLHttpRequest class for IE 5.x-6.x:
jasmine . XmlHttpRequest = ( typeof XMLHttpRequest == "undefined" ) ? function ( ) {
2012-06-30 18:13:02 +08:00
function tryIt ( f ) {
try {
return f ( ) ;
} catch ( e ) {
}
return null ;
2010-09-02 18:45:04 +08:00
}
2012-06-30 18:13:02 +08:00
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 ;
2010-09-02 18:45:04 +08:00
} : 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 ;
2012-06-30 18:13:02 +08:00
childClass . prototype = new subclass ( ) ;
2010-09-02 18:45:04 +08:00
} ;
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 ( ) {
2012-06-30 18:13:02 +08:00
if ( ! jasmine . version _ ) {
2010-09-02 18:45:04 +08:00
return "version unknown" ;
}
2012-06-30 18:13:02 +08:00
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 ;
2010-09-02 18:45:04 +08:00
} ;
/ * *
* @ 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 ;
} ) ;
}
2012-06-30 18:13:02 +08:00
this . currentSuite = parentSuite ;
2010-09-02 18:45:04 +08:00
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 . 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 ) {
2012-06-30 18:13:02 +08:00
return obj !== null && obj [ keyName ] !== jasmine . undefined ;
2010-09-02 18:45:04 +08:00
} ;
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 _ _ ;
2012-06-30 18:13:02 +08:00
return ( mismatchKeys . length === 0 && mismatchValues . length === 0 ) ;
2010-09-02 18:45:04 +08:00
} ;
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 ( ) ;
}
2012-06-30 18:13:02 +08:00
if ( a . jasmineMatches ) {
return a . jasmineMatches ( b ) ;
}
if ( b . jasmineMatches ) {
return b . jasmineMatches ( a ) ;
}
if ( a instanceof jasmine . Matchers . ObjectContaining ) {
2010-09-02 18:45:04 +08:00
return a . matches ( b ) ;
}
2012-06-30 18:13:02 +08:00
if ( b instanceof jasmine . Matchers . ObjectContaining ) {
2010-09-02 18:45:04 +08:00
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 ( 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 ) ;
} ;
/ * * N o - o p b a s e c l a s s f o r J a s m i n e r e p o r t e r s .
*
* @ constructor
* /
jasmine . Reporter = function ( ) {
} ;
//noinspection JSUnusedLocalSymbols
jasmine . Reporter . prototype . reportRunnerStarting = function ( runner ) {
} ;
//noinspection JSUnusedLocalSymbols
jasmine . Reporter . prototype . reportRunnerResults = function ( runner ) {
} ;
//noinspection JSUnusedLocalSymbols
jasmine . Reporter . prototype . reportSuiteResults = function ( suite ) {
} ;
//noinspection JSUnusedLocalSymbols
jasmine . Reporter . prototype . reportSpecStarting = function ( spec ) {
} ;
//noinspection JSUnusedLocalSymbols
jasmine . Reporter . prototype . reportSpecResults = function ( spec ) {
} ;
//noinspection JSUnusedLocalSymbols
jasmine . 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 ) {
try {
this . func . apply ( this . spec ) ;
} catch ( e ) {
this . spec . fail ( e ) ;
}
onComplete ( ) ;
} ;
/ * * J a v a S c r i p t A P I r e p o r t e r .
*
* @ 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 JSUnusedLocalSymbols
jasmine . JsApiReporter . prototype . reportRunnerResults = function ( runner ) {
this . finished = true ;
} ;
//noinspection JSUnusedLocalSymbols
jasmine . JsApiReporter . prototype . reportSuiteResults = function ( suite ) {
} ;
//noinspection JSUnusedLocalSymbols
jasmine . JsApiReporter . prototype . reportSpecResults = function ( spec ) {
this . results _ [ spec . id ] = {
messages : spec . results ( ) . getItems ( ) ,
result : spec . results ( ) . failedCount > 0 ? "failed" : "passed"
} ;
} ;
//noinspection JSUnusedLocalSymbols
jasmine . 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
2012-06-30 18:13:02 +08:00
* @ deprecated as of 1.0 . Use not . toEqual ( ) instead .
2010-09-02 18:45:04 +08:00
* /
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 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 ( ) {
2012-06-30 18:13:02 +08:00
if ( this . actual . callCount === 0 ) {
2010-09-02 18:45:04 +08:00
// todo: what should the failure message for .not.toHaveBeenCalledWith() be? is this right? test better. [xw]
return [
2012-06-30 18:13:02 +08:00
"Expected spy " + this . actual . identity + " to have been called with " + jasmine . pp ( expectedArgs ) + " but it was never called." ,
"Expected spy " + this . actual . identity + " not to have been called with " + jasmine . pp ( expectedArgs ) + " but it was."
2010-09-02 18:45:04 +08:00
] ;
} else {
return [
2012-06-30 18:13:02 +08:00
"Expected spy " + this . actual . identity + " to have been called with " + jasmine . pp ( expectedArgs ) + " but was called with " + jasmine . pp ( this . actual . argsForCall ) ,
"Expected spy " + this . actual . identity + " not to have been called with " + jasmine . pp ( expectedArgs ) + " but was called with " + jasmine . pp ( this . actual . argsForCall )
2010-09-02 18:45:04 +08:00
] ;
}
} ;
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"
2012-06-30 18:13:02 +08:00
] ;
2010-09-02 18:45:04 +08:00
} ;
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
2012-06-30 18:13:02 +08:00
* @ deprecated as of 1.0 . Use not . toContain ( ) instead .
2010-09-02 18:45:04 +08:00
* /
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 ;
} ;
2012-06-30 18:13:02 +08:00
/ * *
* 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
* /
jasmine . Matchers . prototype . toBeCloseTo = function ( expected , precision ) {
if ( ! ( precision === 0 ) ) {
precision = precision || 2 ;
}
var multiplier = Math . pow ( 10 , precision ) ;
var actual = Math . round ( this . actual * multiplier ) ;
expected = Math . round ( expected * multiplier ) ;
return expected == actual ;
} ;
2010-09-02 18:45:04 +08:00
/ * *
* 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 ) ) ) {
2012-06-30 18:13:02 +08:00
return [ "Expected function " + not + "to throw" , expected ? expected . message || expected : "an exception" , ", but it threw" , exception . message || exception ] . join ( ' ' ) ;
2010-09-02 18:45:04 +08:00
} else {
return "Expected function to throw an exception." ;
}
} ;
return result ;
} ;
jasmine . Matchers . Any = function ( expectedClass ) {
this . expectedClass = expectedClass ;
} ;
2012-06-30 18:13:02 +08:00
jasmine . Matchers . Any . prototype . jasmineMatches = function ( other ) {
2010-09-02 18:45:04 +08:00
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 ;
} ;
2012-06-30 18:13:02 +08:00
jasmine . Matchers . Any . prototype . jasmineToString = function ( ) {
2010-09-02 18:45:04 +08:00
return '<jasmine.any(' + this . expectedClass + ')>' ;
} ;
2012-06-30 18:13:02 +08:00
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.com
jasmine . 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 support
jasmine . 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 ) ;
}
} ;
2010-09-02 18:45:04 +08:00
/ * *
* @ 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 > b e l o w p a s s e d
* /
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 ) {
if ( this . ppNestLevel _ > 40 ) {
throw new Error ( 'jasmine.PrettyPrinter: format() nested too deeply!' ) ;
}
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>' ) ;
2012-06-30 18:13:02 +08:00
} else if ( value . jasmineToString ) {
this . emitScalar ( value . jasmineToString ( ) ) ;
2010-09-02 18:45:04 +08:00
} 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 ( property == '__Jasmine_been_here_before__' ) continue ;
2012-06-30 18:13:02 +08:00
fn ( property , obj . _ _lookupGetter _ _ ? ( obj . _ _lookupGetter _ _ ( property ) !== jasmine . undefined &&
obj . _ _lookupGetter _ _ ( property ) !== null ) : false ) ;
2010-09-02 18:45:04 +08:00
}
} ;
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 ) {
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 ) {
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 ;
this . blocks = [ ] ;
this . running = false ;
this . index = 0 ;
this . offset = 0 ;
this . abort = false ;
} ;
jasmine . Queue . prototype . addBefore = function ( block ) {
this . blocks . unshift ( block ) ;
} ;
jasmine . Queue . prototype . add = function ( block ) {
this . blocks . push ( block ) ;
} ;
jasmine . Queue . prototype . insertNext = function ( block ) {
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 ) {
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 < / c o d e > i n p r o d u c t i o n c o d e .
* /
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 ,
2012-06-30 18:13:02 +08:00
message : e ? jasmine . util . formatException ( e ) : 'Exception' ,
trace : { stack : e . stack }
2010-09-02 18:45:04 +08:00
} ) ;
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 ) ) ;
} 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 ) ) ;
}
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 ) ) ;
}
}
for ( i = 0 ; i < runner . after _ . length ; i ++ ) {
this . queue . add ( new jasmine . Block ( this . env , runner . after _ [ i ] , this ) ) ;
}
} ;
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 ) {
2012-06-30 18:13:02 +08:00
if ( jasmine . VERBOSE ) {
this . env . reporter . log ( '>> Jasmine waiting for ' + this . timeout + ' ms...' ) ;
}
2010-09-02 18:45:04 +08:00
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 ) {
2012-06-30 18:13:02 +08:00
if ( jasmine . VERBOSE ) {
this . env . reporter . log ( '>> Jasmine waiting for ' + ( this . message || 'something to happen' ) ) ;
}
2010-09-02 18:45:04 +08:00
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 ,
2012-06-30 18:13:02 +08:00
"minor" : 2 ,
"build" : 0 ,
"revision" : 1337005947
2010-09-02 18:45:04 +08:00
} ;