2013-10-25 11:16:14 +08:00
/ *
Copyright ( c ) 2008 - 2013 Pivotal Labs
Permission is hereby granted , free of charge , to any person obtaining
a copy of this software and associated documentation files ( the
"Software" ) , to deal in the Software without restriction , including
without limitation the rights to use , copy , modify , merge , publish ,
distribute , sublicense , and / or sell copies of the Software , and to
permit persons to whom the Software is furnished to do so , subject to
the following conditions :
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software .
THE SOFTWARE IS PROVIDED "AS IS" , WITHOUT WARRANTY OF ANY KIND ,
EXPRESS OR IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY , FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT . IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM , DAMAGES OR OTHER LIABILITY , WHETHER IN AN ACTION
OF CONTRACT , TORT OR OTHERWISE , ARISING FROM , OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE .
* /
function getJasmineRequireObj ( ) {
if ( typeof module !== "undefined" && module . exports ) {
return exports ;
} else {
window . jasmineRequire = window . jasmineRequire || { } ;
return window . jasmineRequire ;
}
}
getJasmineRequireObj ( ) . core = function ( jRequire ) {
var j$ = { } ;
jRequire . base ( j$ ) ;
j$ . util = jRequire . util ( ) ;
j$ . Any = jRequire . Any ( ) ;
j$ . CallTracker = jRequire . CallTracker ( ) ;
j$ . Clock = jRequire . Clock ( ) ;
j$ . DelayedFunctionScheduler = jRequire . DelayedFunctionScheduler ( ) ;
j$ . Env = jRequire . Env ( j$ ) ;
j$ . ExceptionFormatter = jRequire . ExceptionFormatter ( ) ;
j$ . Expectation = jRequire . Expectation ( ) ;
j$ . buildExpectationResult = jRequire . buildExpectationResult ( ) ;
j$ . JsApiReporter = jRequire . JsApiReporter ( ) ;
j$ . matchersUtil = jRequire . matchersUtil ( j$ ) ;
j$ . ObjectContaining = jRequire . ObjectContaining ( j$ ) ;
j$ . pp = jRequire . pp ( j$ ) ;
j$ . QueueRunner = jRequire . QueueRunner ( ) ;
j$ . ReportDispatcher = jRequire . ReportDispatcher ( ) ;
j$ . Spec = jRequire . Spec ( j$ ) ;
j$ . SpyStrategy = jRequire . SpyStrategy ( ) ;
j$ . Suite = jRequire . Suite ( ) ;
j$ . Timer = jRequire . Timer ( ) ;
j$ . version = jRequire . version ( ) ;
j$ . matchers = jRequire . requireMatchers ( jRequire , j$ ) ;
return j$ ;
} ;
getJasmineRequireObj ( ) . requireMatchers = function ( jRequire , j$ ) {
var availableMatchers = [
"toBe" ,
"toBeCloseTo" ,
"toBeDefined" ,
"toBeFalsy" ,
"toBeGreaterThan" ,
"toBeLessThan" ,
"toBeNaN" ,
"toBeNull" ,
"toBeTruthy" ,
"toBeUndefined" ,
"toContain" ,
"toEqual" ,
"toHaveBeenCalled" ,
"toHaveBeenCalledWith" ,
"toMatch" ,
"toThrow" ,
"toThrowError"
] ,
matchers = { } ;
for ( var i = 0 ; i < availableMatchers . length ; i ++ ) {
var name = availableMatchers [ i ] ;
matchers [ name ] = jRequire [ name ] ( j$ ) ;
}
return matchers ;
} ;
getJasmineRequireObj ( ) . base = function ( j$ ) {
j$ . unimplementedMethod _ = function ( ) {
throw new Error ( "unimplemented method" ) ;
} ;
j$ . MAX _PRETTY _PRINT _DEPTH = 40 ;
j$ . DEFAULT _TIMEOUT _INTERVAL = 5000 ;
j$ . getGlobal = function ( ) {
function getGlobal ( ) {
return this ;
}
return getGlobal ( ) ;
} ;
j$ . getEnv = function ( options ) {
var env = j$ . currentEnv _ = j$ . currentEnv _ || new j$ . Env ( options ) ;
//jasmine. singletons in here (setTimeout blah blah).
return env ;
} ;
j$ . isArray _ = function ( value ) {
return j$ . isA _ ( "Array" , value ) ;
} ;
j$ . isString _ = function ( value ) {
return j$ . isA _ ( "String" , value ) ;
} ;
j$ . isNumber _ = function ( value ) {
return j$ . isA _ ( "Number" , value ) ;
} ;
j$ . isA _ = function ( typeName , value ) {
return Object . prototype . toString . apply ( value ) === '[object ' + typeName + ']' ;
} ;
j$ . isDomNode = function ( obj ) {
return obj . nodeType > 0 ;
} ;
j$ . any = function ( clazz ) {
return new j$ . Any ( clazz ) ;
} ;
j$ . objectContaining = function ( sample ) {
return new j$ . ObjectContaining ( sample ) ;
} ;
j$ . createSpy = function ( name , originalFn ) {
var spyStrategy = new j$ . SpyStrategy ( {
2013-10-31 02:00:50 +08:00
name : name ,
fn : originalFn ,
getSpy : function ( ) { return spy ; }
} ) ,
callTracker = new j$ . CallTracker ( ) ,
spy = function ( ) {
callTracker . track ( {
object : this ,
args : Array . prototype . slice . apply ( arguments )
} ) ;
return spyStrategy . exec . apply ( this , arguments ) ;
} ;
2013-10-25 11:16:14 +08:00
for ( var prop in originalFn ) {
if ( prop === 'and' || prop === 'calls' ) {
throw new Error ( "Jasmine spies would overwrite the 'and' and 'calls' properties on the object being spied upon" ) ;
}
spy [ prop ] = originalFn [ prop ] ;
}
spy . and = spyStrategy ;
spy . calls = callTracker ;
return spy ;
} ;
j$ . isSpy = function ( putativeSpy ) {
if ( ! putativeSpy ) {
return false ;
}
return putativeSpy . and instanceof j$ . SpyStrategy &&
2013-10-31 02:00:50 +08:00
putativeSpy . calls instanceof j$ . CallTracker ;
2013-10-25 11:16:14 +08:00
} ;
j$ . createSpyObj = function ( baseName , methodNames ) {
if ( ! j$ . isArray _ ( methodNames ) || methodNames . length === 0 ) {
throw "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 ] ] = j$ . createSpy ( baseName + '.' + methodNames [ i ] ) ;
}
return obj ;
} ;
} ;
getJasmineRequireObj ( ) . util = function ( ) {
var util = { } ;
util . inherit = function ( childClass , parentClass ) {
2013-10-31 02:00:50 +08:00
var Subclass = function ( ) {
2013-10-25 11:16:14 +08:00
} ;
2013-10-31 02:00:50 +08:00
Subclass . prototype = parentClass . prototype ;
childClass . prototype = new Subclass ( ) ;
2013-10-25 11:16:14 +08:00
} ;
util . htmlEscape = function ( str ) {
2013-10-31 02:00:50 +08:00
if ( ! str ) {
return str ;
}
2013-10-25 11:16:14 +08:00
return str . replace ( /&/g , '&' )
. replace ( /</g , '<' )
. replace ( />/g , '>' ) ;
} ;
util . argsToArray = function ( args ) {
var arrayOfArgs = [ ] ;
2013-10-31 02:00:50 +08:00
for ( var i = 0 ; i < args . length ; i ++ ) {
arrayOfArgs . push ( args [ i ] ) ;
}
2013-10-25 11:16:14 +08:00
return arrayOfArgs ;
} ;
util . isUndefined = function ( obj ) {
return obj === void 0 ;
} ;
return util ;
} ;
getJasmineRequireObj ( ) . Spec = function ( j$ ) {
function Spec ( attrs ) {
this . expectationFactory = attrs . expectationFactory ;
this . resultCallback = attrs . resultCallback || function ( ) { } ;
this . id = attrs . id ;
this . description = attrs . description || '' ;
this . fn = attrs . fn ;
this . beforeFns = attrs . beforeFns || function ( ) { } ;
this . afterFns = attrs . afterFns || function ( ) { } ;
this . catchingExceptions = attrs . catchingExceptions ;
this . onStart = attrs . onStart || function ( ) { } ;
this . exceptionFormatter = attrs . exceptionFormatter || function ( ) { } ;
this . getSpecName = attrs . getSpecName || function ( ) { return '' ; } ;
this . expectationResultFactory = attrs . expectationResultFactory || function ( ) { } ;
this . queueRunner = attrs . queueRunner || function ( ) { } ;
this . catchingExceptions = attrs . catchingExceptions || function ( ) { return true ; } ;
this . timer = attrs . timer || { setTimeout : setTimeout , clearTimeout : clearTimeout } ;
if ( ! this . fn ) {
this . pend ( ) ;
}
this . result = {
id : this . id ,
description : this . description ,
fullName : this . getFullName ( ) ,
failedExpectations : [ ]
} ;
}
Spec . prototype . addExpectationResult = function ( passed , data ) {
if ( passed ) {
return ;
}
this . result . failedExpectations . push ( this . expectationResultFactory ( data ) ) ;
} ;
Spec . prototype . expect = function ( actual ) {
return this . expectationFactory ( actual , this ) ;
} ;
Spec . prototype . execute = function ( onComplete ) {
var self = this ;
this . onStart ( this ) ;
if ( this . markedPending || this . disabled ) {
complete ( ) ;
return ;
}
function timeoutable ( fn ) {
return function ( done ) {
var timeout = Function . prototype . apply . apply ( self . timer . setTimeout , [ j$ . getGlobal ( ) , [ function ( ) {
2013-10-31 02:00:50 +08:00
onException ( new Error ( 'Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.' ) ) ;
2013-10-25 11:16:14 +08:00
done ( ) ;
} , j$ . DEFAULT _TIMEOUT _INTERVAL ] ] ) ;
var callDone = function ( ) {
Function . prototype . apply . apply ( self . timer . clearTimeout , [ j$ . getGlobal ( ) , [ timeout ] ] ) ;
done ( ) ;
} ;
fn . call ( this , callDone ) ; //TODO: do we care about more than 1 arg?
} ;
}
var befores = this . beforeFns ( ) || [ ] ,
2013-10-31 02:00:50 +08:00
afters = this . afterFns ( ) || [ ] ,
thisOne = ( this . fn . length ) ? timeoutable ( this . fn ) : this . fn ;
2013-10-25 11:16:14 +08:00
var allFns = befores . concat ( thisOne ) . concat ( afters ) ;
this . queueRunner ( {
fns : allFns ,
onException : onException ,
onComplete : complete
} ) ;
function onException ( e ) {
2013-10-31 02:00:50 +08:00
if ( Spec . isPendingSpecException ( e ) ) {
self . pend ( ) ;
return ;
}
2013-10-25 11:16:14 +08:00
2013-10-31 02:00:50 +08:00
self . addExpectationResult ( false , {
matcherName : "" ,
passed : false ,
expected : "" ,
actual : "" ,
error : e
} ) ;
2013-10-25 11:16:14 +08:00
}
function complete ( ) {
self . result . status = self . status ( ) ;
self . resultCallback ( self . result ) ;
if ( onComplete ) {
onComplete ( ) ;
}
}
} ;
Spec . prototype . disable = function ( ) {
this . disabled = true ;
} ;
Spec . prototype . pend = function ( ) {
this . markedPending = true ;
} ;
Spec . prototype . status = function ( ) {
if ( this . disabled ) {
return 'disabled' ;
}
2013-10-31 02:00:50 +08:00
if ( this . markedPending ) {
2013-10-25 11:16:14 +08:00
return 'pending' ;
}
if ( this . result . failedExpectations . length > 0 ) {
return 'failed' ;
} else {
return 'passed' ;
}
} ;
Spec . prototype . getFullName = function ( ) {
return this . getSpecName ( this ) ;
} ;
Spec . pendingSpecExceptionMessage = "=> marked Pending" ;
Spec . isPendingSpecException = function ( e ) {
return e . toString ( ) . indexOf ( Spec . pendingSpecExceptionMessage ) !== - 1 ;
} ;
return Spec ;
} ;
if ( typeof window == void 0 && typeof exports == "object" ) {
exports . Spec = jasmineRequire . Spec ;
}
getJasmineRequireObj ( ) . Env = function ( j$ ) {
function Env ( options ) {
options = options || { } ;
var self = this ;
var global = options . global || j$ . getGlobal ( ) ;
2013-10-31 02:00:50 +08:00
var totalSpecsDefined = 0 ;
2013-10-25 11:16:14 +08:00
var catchExceptions = true ;
var realSetTimeout = j$ . getGlobal ( ) . setTimeout ;
var realClearTimeout = j$ . getGlobal ( ) . clearTimeout ;
this . clock = new j$ . Clock ( global , new j$ . DelayedFunctionScheduler ( ) ) ;
var runnableLookupTable = { } ;
var spies = [ ] ;
2013-10-31 02:00:50 +08:00
var currentSpec = null ;
var currentSuite = null ;
2013-10-25 11:16:14 +08:00
2013-10-31 02:00:50 +08:00
var reporter = new j$ . ReportDispatcher ( [
2013-10-25 11:16:14 +08:00
"jasmineStarted" ,
"jasmineDone" ,
"suiteStarted" ,
"suiteDone" ,
"specStarted" ,
"specDone"
] ) ;
this . specFilter = function ( ) {
return true ;
} ;
2013-10-31 02:00:50 +08:00
var equalityTesters = [ ] ;
2013-10-25 11:16:14 +08:00
var customEqualityTesters = [ ] ;
this . addCustomEqualityTester = function ( tester ) {
customEqualityTesters . push ( tester ) ;
} ;
j$ . Expectation . addCoreMatchers ( j$ . matchers ) ;
2013-10-31 02:00:50 +08:00
var nextSpecId = 0 ;
var getNextSpecId = function ( ) {
return 'spec' + nextSpecId ++ ;
} ;
var nextSuiteId = 0 ;
var getNextSuiteId = function ( ) {
return 'suite' + nextSuiteId ++ ;
} ;
2013-10-25 11:16:14 +08:00
var expectationFactory = function ( actual , spec ) {
return j$ . Expectation . Factory ( {
util : j$ . matchersUtil ,
customEqualityTesters : customEqualityTesters ,
actual : actual ,
addExpectationResult : addExpectationResult
} ) ;
function addExpectationResult ( passed , result ) {
return spec . addExpectationResult ( passed , result ) ;
}
} ;
var specStarted = function ( spec ) {
2013-10-31 02:00:50 +08:00
currentSpec = spec ;
reporter . specStarted ( spec . result ) ;
2013-10-25 11:16:14 +08:00
} ;
2013-10-31 02:00:50 +08:00
var beforeFns = function ( suite ) {
2013-10-25 11:16:14 +08:00
return function ( ) {
var befores = [ ] ;
2013-10-31 02:00:50 +08:00
while ( suite ) {
2013-10-25 11:16:14 +08:00
befores = befores . concat ( suite . beforeFns ) ;
2013-10-31 02:00:50 +08:00
suite = suite . parentSuite ;
2013-10-25 11:16:14 +08:00
}
return befores . reverse ( ) ;
} ;
} ;
2013-10-31 02:00:50 +08:00
var afterFns = function ( suite ) {
2013-10-25 11:16:14 +08:00
return function ( ) {
var afters = [ ] ;
2013-10-31 02:00:50 +08:00
while ( suite ) {
2013-10-25 11:16:14 +08:00
afters = afters . concat ( suite . afterFns ) ;
2013-10-31 02:00:50 +08:00
suite = suite . parentSuite ;
2013-10-25 11:16:14 +08:00
}
return afters ;
} ;
} ;
2013-10-31 02:00:50 +08:00
var getSpecName = function ( spec , suite ) {
return suite . getFullName ( ) + ' ' + spec . description ;
2013-10-25 11:16:14 +08:00
} ;
// TODO: we may just be able to pass in the fn instead of wrapping here
var buildExpectationResult = j$ . buildExpectationResult ,
exceptionFormatter = new j$ . ExceptionFormatter ( ) ,
expectationResultFactory = function ( attrs ) {
attrs . messageFormatter = exceptionFormatter . message ;
attrs . stackFormatter = exceptionFormatter . stack ;
return buildExpectationResult ( attrs ) ;
} ;
// TODO: fix this naming, and here's where the value comes in
this . catchExceptions = function ( value ) {
catchExceptions = ! ! value ;
return catchExceptions ;
} ;
this . catchingExceptions = function ( ) {
return catchExceptions ;
} ;
var maximumSpecCallbackDepth = 20 ;
var currentSpecCallbackDepth = 0 ;
function clearStack ( fn ) {
currentSpecCallbackDepth ++ ;
if ( currentSpecCallbackDepth >= maximumSpecCallbackDepth ) {
currentSpecCallbackDepth = 0 ;
realSetTimeout ( fn , 0 ) ;
} else {
fn ( ) ;
}
}
2013-10-31 02:00:50 +08:00
var catchException = function ( e ) {
return j$ . Spec . isPendingSpecException ( e ) || catchExceptions ;
2013-10-25 11:16:14 +08:00
} ;
2013-10-31 02:00:50 +08:00
var queueRunnerFactory = function ( options ) {
options . catchException = catchException ;
options . clearStack = options . clearStack || clearStack ;
2013-10-25 11:16:14 +08:00
2013-10-31 02:00:50 +08:00
new j$ . QueueRunner ( options ) . execute ( ) ;
2013-10-25 11:16:14 +08:00
} ;
2013-10-31 02:00:50 +08:00
var topSuite = new j$ . Suite ( {
2013-10-25 11:16:14 +08:00
env : this ,
2013-10-31 02:00:50 +08:00
id : getNextSuiteId ( ) ,
2013-10-25 11:16:14 +08:00
description : 'Jasmine__TopLevel__Suite' ,
queueRunner : queueRunnerFactory ,
resultCallback : function ( ) { } // TODO - hook this up
} ) ;
2013-10-31 02:00:50 +08:00
runnableLookupTable [ topSuite . id ] = topSuite ;
currentSuite = topSuite ;
2013-10-25 11:16:14 +08:00
2013-10-31 02:00:50 +08:00
this . topSuite = function ( ) {
return topSuite ;
2013-10-25 11:16:14 +08:00
} ;
this . execute = function ( runnablesToRun ) {
2013-10-31 02:00:50 +08:00
runnablesToRun = runnablesToRun || [ topSuite . id ] ;
2013-10-25 11:16:14 +08:00
var allFns = [ ] ;
for ( var i = 0 ; i < runnablesToRun . length ; i ++ ) {
var runnable = runnableLookupTable [ runnablesToRun [ i ] ] ;
allFns . push ( ( function ( runnable ) { return function ( done ) { runnable . execute ( done ) ; } ; } ) ( runnable ) ) ;
}
2013-10-31 02:00:50 +08:00
reporter . jasmineStarted ( {
2013-10-25 11:16:14 +08:00
totalSpecsDefined : totalSpecsDefined
} ) ;
2013-10-31 02:00:50 +08:00
queueRunnerFactory ( { fns : allFns , onComplete : reporter . jasmineDone } ) ;
} ;
this . addReporter = function ( reporterToAdd ) {
reporter . addReporter ( reporterToAdd ) ;
} ;
this . addMatchers = function ( matchersToAdd ) {
j$ . Expectation . addMatchers ( matchersToAdd ) ;
2013-10-25 11:16:14 +08:00
} ;
this . spyOn = function ( obj , methodName ) {
if ( j$ . util . isUndefined ( obj ) ) {
throw new Error ( "spyOn could not find an object to spy upon for " + methodName + "()" ) ;
}
if ( j$ . util . isUndefined ( obj [ methodName ] ) ) {
throw new Error ( methodName + '() method does not exist' ) ;
}
if ( obj [ methodName ] && j$ . isSpy ( obj [ methodName ] ) ) {
//TODO?: should this return the current spy? Downside: may cause user confusion about spy state
throw new Error ( methodName + ' has already been spied upon' ) ;
}
var spy = j$ . createSpy ( methodName , obj [ methodName ] ) ;
spies . push ( {
spy : spy ,
baseObj : obj ,
methodName : methodName ,
originalValue : obj [ methodName ]
} ) ;
obj [ methodName ] = spy ;
return spy ;
} ;
2013-10-31 02:00:50 +08:00
var suiteFactory = function ( description ) {
var suite = new j$ . Suite ( {
env : self ,
id : getNextSuiteId ( ) ,
description : description ,
parentSuite : currentSuite ,
queueRunner : queueRunnerFactory ,
onStart : suiteStarted ,
resultCallback : function ( attrs ) {
reporter . suiteDone ( attrs ) ;
}
} ) ;
2013-10-25 11:16:14 +08:00
2013-10-31 02:00:50 +08:00
runnableLookupTable [ suite . id ] = suite ;
return suite ;
} ;
2013-10-25 11:16:14 +08:00
2013-10-31 02:00:50 +08:00
this . describe = function ( description , specDefinitions ) {
var suite = suiteFactory ( description ) ;
2013-10-25 11:16:14 +08:00
2013-10-31 02:00:50 +08:00
var parentSuite = currentSuite ;
parentSuite . addChild ( suite ) ;
currentSuite = suite ;
2013-10-25 11:16:14 +08:00
2013-10-31 02:00:50 +08:00
var declarationError = null ;
try {
specDefinitions . call ( suite ) ;
} catch ( e ) {
declarationError = e ;
}
2013-10-25 11:16:14 +08:00
2013-10-31 02:00:50 +08:00
if ( declarationError ) {
this . it ( "encountered a declaration exception" , function ( ) {
throw declarationError ;
} ) ;
}
2013-10-25 11:16:14 +08:00
2013-10-31 02:00:50 +08:00
currentSuite = parentSuite ;
2013-10-25 11:16:14 +08:00
2013-10-31 02:00:50 +08:00
return suite ;
} ;
2013-10-25 11:16:14 +08:00
2013-10-31 02:00:50 +08:00
this . xdescribe = function ( description , specDefinitions ) {
var suite = this . describe ( description , specDefinitions ) ;
suite . disable ( ) ;
return suite ;
} ;
2013-10-25 11:16:14 +08:00
2013-10-31 02:00:50 +08:00
var specFactory = function ( description , fn , suite ) {
totalSpecsDefined ++ ;
2013-10-25 11:16:14 +08:00
2013-10-31 02:00:50 +08:00
var spec = new j$ . Spec ( {
id : getNextSpecId ( ) ,
beforeFns : beforeFns ( suite ) ,
afterFns : afterFns ( suite ) ,
expectationFactory : expectationFactory ,
exceptionFormatter : exceptionFormatter ,
resultCallback : specResultCallback ,
getSpecName : function ( spec ) {
return getSpecName ( spec , suite ) ;
} ,
onStart : specStarted ,
description : description ,
expectationResultFactory : expectationResultFactory ,
queueRunner : queueRunnerFactory ,
fn : fn ,
timer : { setTimeout : realSetTimeout , clearTimeout : realClearTimeout }
2013-10-25 11:16:14 +08:00
} ) ;
2013-10-31 02:00:50 +08:00
runnableLookupTable [ spec . id ] = spec ;
2013-10-25 11:16:14 +08:00
2013-10-31 02:00:50 +08:00
if ( ! self . specFilter ( spec ) ) {
spec . disable ( ) ;
}
2013-10-25 11:16:14 +08:00
2013-10-31 02:00:50 +08:00
return spec ;
2013-10-25 11:16:14 +08:00
2013-10-31 02:00:50 +08:00
function removeAllSpies ( ) {
for ( var i = 0 ; i < spies . length ; i ++ ) {
var spyEntry = spies [ i ] ;
spyEntry . baseObj [ spyEntry . methodName ] = spyEntry . originalValue ;
}
spies = [ ] ;
}
2013-10-25 11:16:14 +08:00
2013-10-31 02:00:50 +08:00
function specResultCallback ( result ) {
removeAllSpies ( ) ;
j$ . Expectation . resetMatchers ( ) ;
customEqualityTesters = [ ] ;
currentSpec = null ;
reporter . specDone ( result ) ;
}
} ;
2013-10-25 11:16:14 +08:00
2013-10-31 02:00:50 +08:00
var suiteStarted = function ( suite ) {
reporter . suiteStarted ( suite . result ) ;
} ;
2013-10-25 11:16:14 +08:00
2013-10-31 02:00:50 +08:00
this . it = function ( description , fn ) {
var spec = specFactory ( description , fn , currentSuite ) ;
currentSuite . addChild ( spec ) ;
return spec ;
} ;
2013-10-25 11:16:14 +08:00
2013-10-31 02:00:50 +08:00
this . xit = function ( description , fn ) {
var spec = this . it ( description , fn ) ;
spec . pend ( ) ;
return spec ;
} ;
2013-10-25 11:16:14 +08:00
2013-10-31 02:00:50 +08:00
this . expect = function ( actual ) {
return currentSpec . expect ( actual ) ;
} ;
this . beforeEach = function ( beforeEachFunction ) {
currentSuite . beforeEach ( beforeEachFunction ) ;
} ;
this . afterEach = function ( afterEachFunction ) {
currentSuite . afterEach ( afterEachFunction ) ;
} ;
this . pending = function ( ) {
throw j$ . Spec . pendingSpecExceptionMessage ;
} ;
}
2013-10-25 11:16:14 +08:00
return Env ;
} ;
getJasmineRequireObj ( ) . JsApiReporter = function ( ) {
var noopTimer = {
start : function ( ) { } ,
elapsed : function ( ) { return 0 ; }
} ;
function JsApiReporter ( options ) {
var timer = options . timer || noopTimer ,
status = "loaded" ;
this . started = false ;
this . finished = false ;
this . jasmineStarted = function ( ) {
this . started = true ;
status = 'started' ;
timer . start ( ) ;
} ;
var executionTime ;
this . jasmineDone = function ( ) {
this . finished = true ;
executionTime = timer . elapsed ( ) ;
status = 'done' ;
} ;
this . status = function ( ) {
return status ;
} ;
var suites = { } ;
this . suiteStarted = function ( result ) {
storeSuite ( result ) ;
} ;
this . suiteDone = function ( result ) {
storeSuite ( result ) ;
} ;
function storeSuite ( result ) {
suites [ result . id ] = result ;
}
this . suites = function ( ) {
return suites ;
} ;
var specs = [ ] ;
this . specStarted = function ( result ) { } ;
this . specDone = function ( result ) {
specs . push ( result ) ;
} ;
this . specResults = function ( index , length ) {
return specs . slice ( index , index + length ) ;
} ;
this . specs = function ( ) {
return specs ;
} ;
this . executionTime = function ( ) {
return executionTime ;
} ;
}
return JsApiReporter ;
} ;
getJasmineRequireObj ( ) . Any = function ( ) {
function Any ( expectedObject ) {
this . expectedObject = expectedObject ;
}
Any . prototype . jasmineMatches = function ( other ) {
if ( this . expectedObject == String ) {
return typeof other == 'string' || other instanceof String ;
}
if ( this . expectedObject == Number ) {
return typeof other == 'number' || other instanceof Number ;
}
if ( this . expectedObject == Function ) {
return typeof other == 'function' || other instanceof Function ;
}
if ( this . expectedObject == Object ) {
return typeof other == 'object' ;
}
if ( this . expectedObject == Boolean ) {
return typeof other == 'boolean' ;
}
return other instanceof this . expectedObject ;
} ;
Any . prototype . jasmineToString = function ( ) {
return '<jasmine.any(' + this . expectedClass + ')>' ;
} ;
return Any ;
} ;
2013-10-31 02:00:50 +08:00
2013-10-25 11:16:14 +08:00
getJasmineRequireObj ( ) . CallTracker = function ( ) {
function CallTracker ( ) {
var calls = [ ] ;
this . track = function ( context ) {
calls . push ( context ) ;
} ;
this . any = function ( ) {
return ! ! calls . length ;
} ;
this . count = function ( ) {
return calls . length ;
} ;
this . argsFor = function ( index ) {
var call = calls [ index ] ;
return call ? call . args : [ ] ;
} ;
this . all = function ( ) {
return calls ;
} ;
this . allArgs = function ( ) {
var callArgs = [ ] ;
for ( var i = 0 ; i < calls . length ; i ++ ) {
callArgs . push ( calls [ i ] . args ) ;
}
return callArgs ;
} ;
this . first = function ( ) {
return calls [ 0 ] ;
} ;
this . mostRecent = function ( ) {
return calls [ calls . length - 1 ] ;
} ;
this . reset = function ( ) {
calls = [ ] ;
} ;
}
return CallTracker ;
} ;
getJasmineRequireObj ( ) . Clock = function ( ) {
function Clock ( global , delayedFunctionScheduler ) {
var self = this ,
realTimingFunctions = {
setTimeout : global . setTimeout ,
clearTimeout : global . clearTimeout ,
setInterval : global . setInterval ,
clearInterval : global . clearInterval
} ,
fakeTimingFunctions = {
setTimeout : setTimeout ,
clearTimeout : clearTimeout ,
setInterval : setInterval ,
clearInterval : clearInterval
} ,
2013-10-31 02:00:50 +08:00
installed = false ,
timer ;
2013-10-25 11:16:14 +08:00
self . install = function ( ) {
replace ( global , fakeTimingFunctions ) ;
timer = fakeTimingFunctions ;
installed = true ;
} ;
self . uninstall = function ( ) {
delayedFunctionScheduler . reset ( ) ;
replace ( global , realTimingFunctions ) ;
timer = realTimingFunctions ;
installed = false ;
} ;
self . setTimeout = function ( fn , delay , params ) {
if ( legacyIE ( ) ) {
if ( arguments . length > 2 ) {
throw new Error ( "IE < 9 cannot support extra params to setTimeout without a polyfill" ) ;
}
return timer . setTimeout ( fn , delay ) ;
}
return Function . prototype . apply . apply ( timer . setTimeout , [ global , arguments ] ) ;
} ;
self . setInterval = function ( fn , delay , params ) {
if ( legacyIE ( ) ) {
if ( arguments . length > 2 ) {
throw new Error ( "IE < 9 cannot support extra params to setInterval without a polyfill" ) ;
}
return timer . setInterval ( fn , delay ) ;
}
return Function . prototype . apply . apply ( timer . setInterval , [ global , arguments ] ) ;
} ;
self . clearTimeout = function ( id ) {
return Function . prototype . call . apply ( timer . clearTimeout , [ global , id ] ) ;
} ;
self . clearInterval = function ( id ) {
return Function . prototype . call . apply ( timer . clearInterval , [ global , id ] ) ;
} ;
self . tick = function ( millis ) {
if ( installed ) {
delayedFunctionScheduler . tick ( millis ) ;
} else {
2013-10-31 02:00:50 +08:00
throw new Error ( "Mock clock is not installed, use jasmine.clock().install()" ) ;
2013-10-25 11:16:14 +08:00
}
} ;
return self ;
function legacyIE ( ) {
//if these methods are polyfilled, apply will be present
return ! ( realTimingFunctions . setTimeout || realTimingFunctions . setInterval ) . apply ;
}
function replace ( dest , source ) {
for ( var prop in source ) {
dest [ prop ] = source [ prop ] ;
}
}
function setTimeout ( fn , delay ) {
return delayedFunctionScheduler . scheduleFunction ( fn , delay , argSlice ( arguments , 2 ) ) ;
}
function clearTimeout ( id ) {
return delayedFunctionScheduler . removeFunctionWithId ( id ) ;
}
function setInterval ( fn , interval ) {
return delayedFunctionScheduler . scheduleFunction ( fn , interval , argSlice ( arguments , 2 ) , true ) ;
}
function clearInterval ( id ) {
return delayedFunctionScheduler . removeFunctionWithId ( id ) ;
}
function argSlice ( argsObj , n ) {
return Array . prototype . slice . call ( argsObj , 2 ) ;
}
}
return Clock ;
} ;
getJasmineRequireObj ( ) . DelayedFunctionScheduler = function ( ) {
function DelayedFunctionScheduler ( ) {
var self = this ;
var scheduledFunctions = { } ;
var currentTime = 0 ;
var delayedFnCount = 0 ;
self . tick = function ( millis ) {
millis = millis || 0 ;
currentTime = currentTime + millis ;
runFunctionsWithinRange ( currentTime - millis , currentTime ) ;
} ;
self . scheduleFunction = function ( funcToCall , millis , params , recurring , timeoutKey , runAtMillis ) {
var f ;
if ( typeof ( funcToCall ) === 'string' ) {
/* jshint evil: true */
f = function ( ) { return eval ( funcToCall ) ; } ;
/* jshint evil: false */
} else {
f = funcToCall ;
}
millis = millis || 0 ;
timeoutKey = timeoutKey || ++ delayedFnCount ;
runAtMillis = runAtMillis || ( currentTime + millis ) ;
scheduledFunctions [ timeoutKey ] = {
runAtMillis : runAtMillis ,
funcToCall : f ,
recurring : recurring ,
params : params ,
timeoutKey : timeoutKey ,
millis : millis
} ;
return timeoutKey ;
} ;
self . removeFunctionWithId = function ( timeoutKey ) {
delete scheduledFunctions [ timeoutKey ] ;
} ;
self . reset = function ( ) {
currentTime = 0 ;
scheduledFunctions = { } ;
delayedFnCount = 0 ;
} ;
return self ;
// finds/dupes functions within range and removes them.
function functionsWithinRange ( startMillis , endMillis ) {
var fnsToRun = [ ] ;
for ( var timeoutKey in scheduledFunctions ) {
var scheduledFunc = scheduledFunctions [ timeoutKey ] ;
if ( scheduledFunc &&
scheduledFunc . runAtMillis >= startMillis &&
scheduledFunc . runAtMillis <= endMillis ) {
// remove fn -- we'll reschedule later if it is recurring.
self . removeFunctionWithId ( timeoutKey ) ;
if ( ! scheduledFunc . recurring ) {
fnsToRun . push ( scheduledFunc ) ; // schedules each function only once
} else {
fnsToRun . push ( buildNthInstanceOf ( scheduledFunc , 0 ) ) ;
var additionalTimesFnRunsInRange =
Math . floor ( ( endMillis - scheduledFunc . runAtMillis ) / scheduledFunc . millis ) ;
for ( var i = 0 ; i < additionalTimesFnRunsInRange ; i ++ ) {
fnsToRun . push ( buildNthInstanceOf ( scheduledFunc , i + 1 ) ) ;
}
reschedule ( buildNthInstanceOf ( scheduledFunc , additionalTimesFnRunsInRange ) ) ;
}
}
}
return fnsToRun ;
}
function buildNthInstanceOf ( scheduledFunc , n ) {
return {
runAtMillis : scheduledFunc . runAtMillis + ( scheduledFunc . millis * n ) ,
funcToCall : scheduledFunc . funcToCall ,
params : scheduledFunc . params ,
millis : scheduledFunc . millis ,
recurring : scheduledFunc . recurring ,
timeoutKey : scheduledFunc . timeoutKey
} ;
}
function reschedule ( scheduledFn ) {
self . scheduleFunction ( scheduledFn . funcToCall ,
scheduledFn . millis ,
scheduledFn . params ,
true ,
scheduledFn . timeoutKey ,
scheduledFn . runAtMillis + scheduledFn . millis ) ;
}
function runFunctionsWithinRange ( startMillis , endMillis ) {
var funcsToRun = functionsWithinRange ( startMillis , endMillis ) ;
if ( funcsToRun . length === 0 ) {
return ;
}
funcsToRun . sort ( function ( a , b ) {
return a . runAtMillis - b . runAtMillis ;
} ) ;
for ( var i = 0 ; i < funcsToRun . length ; ++ i ) {
var funcToRun = funcsToRun [ i ] ;
funcToRun . funcToCall . apply ( null , funcToRun . params || [ ] ) ;
}
}
}
return DelayedFunctionScheduler ;
} ;
getJasmineRequireObj ( ) . ExceptionFormatter = function ( ) {
function ExceptionFormatter ( ) {
this . message = function ( error ) {
var message = error . name +
': ' +
error . message ;
if ( error . fileName || error . sourceURL ) {
message += " in " + ( error . fileName || error . sourceURL ) ;
}
if ( error . line || error . lineNumber ) {
message += " (line " + ( error . line || error . lineNumber ) + ")" ;
}
return message ;
} ;
this . stack = function ( error ) {
return error ? error . stack : null ;
} ;
}
return ExceptionFormatter ;
} ;
getJasmineRequireObj ( ) . Expectation = function ( ) {
var matchers = { } ;
function Expectation ( options ) {
this . util = options . util || { buildFailureMessage : function ( ) { } } ;
this . customEqualityTesters = options . customEqualityTesters || [ ] ;
this . actual = options . actual ;
this . addExpectationResult = options . addExpectationResult || function ( ) { } ;
this . isNot = options . isNot ;
for ( var matcherName in matchers ) {
this [ matcherName ] = matchers [ matcherName ] ;
}
}
Expectation . prototype . wrapCompare = function ( name , matcherFactory ) {
return function ( ) {
var args = Array . prototype . slice . call ( arguments , 0 ) ,
expected = args . slice ( 0 ) ,
message = "" ;
args . unshift ( this . actual ) ;
2013-10-31 02:00:50 +08:00
var matcher = matcherFactory ( this . util , this . customEqualityTesters ) ,
matcherCompare = matcher . compare ;
2013-10-25 11:16:14 +08:00
2013-10-31 02:00:50 +08:00
function defaultNegativeCompare ( ) {
var result = matcher . compare . apply ( null , args ) ;
2013-10-25 11:16:14 +08:00
result . pass = ! result . pass ;
2013-10-31 02:00:50 +08:00
return result ;
}
if ( this . isNot ) {
matcherCompare = matcher . negativeCompare || defaultNegativeCompare ;
2013-10-25 11:16:14 +08:00
}
2013-10-31 02:00:50 +08:00
var result = matcherCompare . apply ( null , args ) ;
2013-10-25 11:16:14 +08:00
if ( ! result . pass ) {
if ( ! result . message ) {
args . unshift ( this . isNot ) ;
args . unshift ( name ) ;
message = this . util . buildFailureMessage . apply ( null , args ) ;
} else {
message = result . message ;
}
}
if ( expected . length == 1 ) {
expected = expected [ 0 ] ;
}
// TODO: how many of these params are needed?
this . addExpectationResult (
result . pass ,
{
matcherName : name ,
passed : result . pass ,
message : message ,
actual : this . actual ,
expected : expected // TODO: this may need to be arrayified/sliced
}
) ;
} ;
} ;
Expectation . addCoreMatchers = function ( matchers ) {
var prototype = Expectation . prototype ;
for ( var matcherName in matchers ) {
var matcher = matchers [ matcherName ] ;
prototype [ matcherName ] = prototype . wrapCompare ( matcherName , matcher ) ;
}
} ;
Expectation . addMatchers = function ( matchersToAdd ) {
for ( var name in matchersToAdd ) {
var matcher = matchersToAdd [ name ] ;
matchers [ name ] = Expectation . prototype . wrapCompare ( name , matcher ) ;
}
} ;
Expectation . resetMatchers = function ( ) {
for ( var name in matchers ) {
delete matchers [ name ] ;
}
} ;
Expectation . Factory = function ( options ) {
options = options || { } ;
var expect = new Expectation ( options ) ;
// TODO: this would be nice as its own Object - NegativeExpectation
// TODO: copy instead of mutate options
options . isNot = true ;
expect . not = new Expectation ( options ) ;
return expect ;
} ;
return Expectation ;
} ;
//TODO: expectation result may make more sense as a presentation of an expectation.
getJasmineRequireObj ( ) . buildExpectationResult = function ( ) {
function buildExpectationResult ( options ) {
var messageFormatter = options . messageFormatter || function ( ) { } ,
stackFormatter = options . stackFormatter || function ( ) { } ;
return {
matcherName : options . matcherName ,
expected : options . expected ,
actual : options . actual ,
message : message ( ) ,
stack : stack ( ) ,
passed : options . passed
} ;
function message ( ) {
if ( options . passed ) {
return "Passed." ;
} else if ( options . message ) {
return options . message ;
} else if ( options . error ) {
return messageFormatter ( options . error ) ;
}
return "" ;
}
function stack ( ) {
if ( options . passed ) {
return "" ;
}
var error = options . error ;
if ( ! error ) {
try {
throw new Error ( message ( ) ) ;
} catch ( e ) {
error = e ;
}
}
return stackFormatter ( error ) ;
}
}
return buildExpectationResult ;
} ;
getJasmineRequireObj ( ) . ObjectContaining = function ( j$ ) {
function ObjectContaining ( sample ) {
this . sample = sample ;
}
ObjectContaining . prototype . jasmineMatches = function ( other , mismatchKeys , mismatchValues ) {
if ( typeof ( this . sample ) !== "object" ) { throw new Error ( "You must provide an object to objectContaining, not '" + this . sample + "'." ) ; }
mismatchKeys = mismatchKeys || [ ] ;
mismatchValues = mismatchValues || [ ] ;
var hasKey = function ( obj , keyName ) {
return obj !== null && ! j$ . util . isUndefined ( obj [ keyName ] ) ;
} ;
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 ( ! j$ . matchersUtil . equals ( this . sample [ property ] , other [ property ] ) ) {
mismatchValues . push ( "'" + property + "' was '" + ( other [ property ] ? j$ . util . htmlEscape ( other [ property ] . toString ( ) ) : other [ property ] ) + "' in actual, but was '" + ( this . sample [ property ] ? j$ . util . htmlEscape ( this . sample [ property ] . toString ( ) ) : this . sample [ property ] ) + "' in expected." ) ;
}
}
return ( mismatchKeys . length === 0 && mismatchValues . length === 0 ) ;
} ;
ObjectContaining . prototype . jasmineToString = function ( ) {
return "<jasmine.objectContaining(" + j$ . pp ( this . sample ) + ")>" ;
} ;
return ObjectContaining ;
} ;
getJasmineRequireObj ( ) . pp = function ( j$ ) {
function PrettyPrinter ( ) {
this . ppNestLevel _ = 0 ;
}
PrettyPrinter . prototype . format = function ( value ) {
this . ppNestLevel _ ++ ;
try {
if ( j$ . util . isUndefined ( value ) ) {
this . emitScalar ( 'undefined' ) ;
} else if ( value === null ) {
this . emitScalar ( 'null' ) ;
} else if ( value === j$ . getGlobal ( ) ) {
this . emitScalar ( '<global>' ) ;
} else if ( value . jasmineToString ) {
this . emitScalar ( value . jasmineToString ( ) ) ;
} else if ( typeof value === 'string' ) {
this . emitString ( value ) ;
} else if ( j$ . isSpy ( value ) ) {
this . emitScalar ( "spy on " + value . and . 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: ' + ( j$ . isArray _ ( value ) ? 'Array' : 'Object' ) + '>' ) ;
} else if ( j$ . isArray _ ( value ) || j$ . isA _ ( 'Object' , value ) ) {
value . _ _Jasmine _been _here _before _ _ = true ;
if ( j$ . isArray _ ( value ) ) {
this . emitArray ( value ) ;
} else {
this . emitObject ( value ) ;
}
delete value . _ _Jasmine _been _here _before _ _ ;
} else {
this . emitScalar ( value . toString ( ) ) ;
}
} finally {
this . ppNestLevel _ -- ;
}
} ;
PrettyPrinter . prototype . iterateObject = function ( obj , fn ) {
for ( var property in obj ) {
2013-10-31 02:00:50 +08:00
if ( ! obj . hasOwnProperty ( property ) ) { continue ; }
if ( property == '__Jasmine_been_here_before__' ) { continue ; }
2013-10-25 11:16:14 +08:00
fn ( property , obj . _ _lookupGetter _ _ ? ( ! j$ . util . isUndefined ( obj . _ _lookupGetter _ _ ( property ) ) &&
obj . _ _lookupGetter _ _ ( property ) !== null ) : false ) ;
}
} ;
PrettyPrinter . prototype . emitArray = j$ . unimplementedMethod _ ;
PrettyPrinter . prototype . emitObject = j$ . unimplementedMethod _ ;
PrettyPrinter . prototype . emitScalar = j$ . unimplementedMethod _ ;
PrettyPrinter . prototype . emitString = j$ . unimplementedMethod _ ;
function StringPrettyPrinter ( ) {
PrettyPrinter . call ( this ) ;
this . string = '' ;
}
j$ . util . inherit ( StringPrettyPrinter , PrettyPrinter ) ;
StringPrettyPrinter . prototype . emitScalar = function ( value ) {
this . append ( value ) ;
} ;
StringPrettyPrinter . prototype . emitString = function ( value ) {
this . append ( "'" + value + "'" ) ;
} ;
StringPrettyPrinter . prototype . emitArray = function ( array ) {
if ( this . ppNestLevel _ > j$ . 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 ( ' ]' ) ;
} ;
StringPrettyPrinter . prototype . emitObject = function ( obj ) {
if ( this . ppNestLevel _ > j$ . 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 ( ' }' ) ;
} ;
StringPrettyPrinter . prototype . append = function ( value ) {
this . string += value ;
} ;
return function ( value ) {
var stringPrettyPrinter = new StringPrettyPrinter ( ) ;
stringPrettyPrinter . format ( value ) ;
return stringPrettyPrinter . string ;
} ;
} ;
getJasmineRequireObj ( ) . QueueRunner = function ( ) {
function QueueRunner ( attrs ) {
this . fns = attrs . fns || [ ] ;
this . onComplete = attrs . onComplete || function ( ) { } ;
this . clearStack = attrs . clearStack || function ( fn ) { fn ( ) ; } ;
this . onException = attrs . onException || function ( ) { } ;
this . catchException = attrs . catchException || function ( ) { return true ; } ;
this . userContext = { } ;
}
QueueRunner . prototype . execute = function ( ) {
this . run ( this . fns , 0 ) ;
} ;
QueueRunner . prototype . run = function ( fns , recursiveIndex ) {
var length = fns . length ,
self = this ,
iterativeIndex ;
for ( iterativeIndex = recursiveIndex ; iterativeIndex < length ; iterativeIndex ++ ) {
var fn = fns [ iterativeIndex ] ;
if ( fn . length > 0 ) {
return attemptAsync ( fn ) ;
} else {
attemptSync ( fn ) ;
}
}
var runnerDone = iterativeIndex >= length ;
if ( runnerDone ) {
this . clearStack ( this . onComplete ) ;
}
function attemptSync ( fn ) {
try {
fn . call ( self . userContext ) ;
} catch ( e ) {
handleException ( e ) ;
}
}
function attemptAsync ( fn ) {
var next = function ( ) { self . run ( fns , iterativeIndex + 1 ) ; } ;
try {
fn . call ( self . userContext , next ) ;
} catch ( e ) {
handleException ( e ) ;
next ( ) ;
}
}
function handleException ( e ) {
self . onException ( e ) ;
if ( ! self . catchException ( e ) ) {
//TODO: set a var when we catch an exception and
//use a finally block to close the loop in a nice way..
throw e ;
}
}
} ;
return QueueRunner ;
} ;
getJasmineRequireObj ( ) . ReportDispatcher = function ( ) {
function ReportDispatcher ( methods ) {
var dispatchedMethods = methods || [ ] ;
for ( var i = 0 ; i < dispatchedMethods . length ; i ++ ) {
var method = dispatchedMethods [ i ] ;
2013-10-31 02:00:50 +08:00
this [ method ] = ( function ( m ) {
2013-10-25 11:16:14 +08:00
return function ( ) {
dispatch ( m , arguments ) ;
} ;
2013-10-31 02:00:50 +08:00
} ( method ) ) ;
2013-10-25 11:16:14 +08:00
}
var reporters = [ ] ;
this . addReporter = function ( reporter ) {
reporters . push ( reporter ) ;
} ;
return this ;
function dispatch ( method , args ) {
for ( var i = 0 ; i < reporters . length ; i ++ ) {
var reporter = reporters [ i ] ;
if ( reporter [ method ] ) {
reporter [ method ] . apply ( reporter , args ) ;
}
}
}
}
return ReportDispatcher ;
} ;
getJasmineRequireObj ( ) . SpyStrategy = function ( ) {
function SpyStrategy ( options ) {
options = options || { } ;
var identity = options . name || "unknown" ,
originalFn = options . fn || function ( ) { } ,
getSpy = options . getSpy || function ( ) { } ,
plan = function ( ) { } ;
this . identity = function ( ) {
return identity ;
} ;
this . exec = function ( ) {
return plan . apply ( this , arguments ) ;
} ;
this . callThrough = function ( ) {
plan = originalFn ;
return getSpy ( ) ;
} ;
this . returnValue = function ( value ) {
plan = function ( ) {
return value ;
} ;
return getSpy ( ) ;
} ;
this . throwError = function ( something ) {
var error = ( something instanceof Error ) ? something : new Error ( something ) ;
plan = function ( ) {
throw error ;
} ;
return getSpy ( ) ;
} ;
this . callFake = function ( fn ) {
plan = fn ;
return getSpy ( ) ;
} ;
this . stub = function ( fn ) {
plan = function ( ) { } ;
return getSpy ( ) ;
} ;
}
return SpyStrategy ;
} ;
getJasmineRequireObj ( ) . Suite = function ( ) {
function Suite ( attrs ) {
this . env = attrs . env ;
this . id = attrs . id ;
this . parentSuite = attrs . parentSuite ;
this . description = attrs . description ;
this . onStart = attrs . onStart || function ( ) { } ;
this . resultCallback = attrs . resultCallback || function ( ) { } ;
this . clearStack = attrs . clearStack || function ( fn ) { fn ( ) ; } ;
this . beforeFns = [ ] ;
this . afterFns = [ ] ;
this . queueRunner = attrs . queueRunner || function ( ) { } ;
this . disabled = false ;
2013-10-31 02:00:50 +08:00
this . children = [ ] ;
2013-10-25 11:16:14 +08:00
this . result = {
id : this . id ,
status : this . disabled ? 'disabled' : '' ,
description : this . description ,
fullName : this . getFullName ( )
} ;
}
Suite . prototype . getFullName = function ( ) {
var fullName = this . description ;
for ( var parentSuite = this . parentSuite ; parentSuite ; parentSuite = parentSuite . parentSuite ) {
if ( parentSuite . parentSuite ) {
fullName = parentSuite . description + ' ' + fullName ;
}
}
return fullName ;
} ;
Suite . prototype . disable = function ( ) {
this . disabled = true ;
} ;
Suite . prototype . beforeEach = function ( fn ) {
this . beforeFns . unshift ( fn ) ;
} ;
Suite . prototype . afterEach = function ( fn ) {
this . afterFns . unshift ( fn ) ;
} ;
2013-10-31 02:00:50 +08:00
Suite . prototype . addChild = function ( child ) {
this . children . push ( child ) ;
2013-10-25 11:16:14 +08:00
} ;
Suite . prototype . execute = function ( onComplete ) {
var self = this ;
if ( this . disabled ) {
complete ( ) ;
return ;
}
2013-10-31 02:00:50 +08:00
var allFns = [ ] ;
2013-10-25 11:16:14 +08:00
2013-10-31 02:00:50 +08:00
for ( var i = 0 ; i < this . children . length ; i ++ ) {
allFns . push ( wrapChildAsAsync ( this . children [ i ] ) ) ;
2013-10-25 11:16:14 +08:00
}
this . onStart ( this ) ;
this . queueRunner ( {
fns : allFns ,
onComplete : complete
} ) ;
function complete ( ) {
self . resultCallback ( self . result ) ;
if ( onComplete ) {
onComplete ( ) ;
}
}
function wrapChildAsAsync ( child ) {
return function ( done ) { child . execute ( done ) ; } ;
}
} ;
2013-10-31 02:00:50 +08:00
2013-10-25 11:16:14 +08:00
return Suite ;
} ;
if ( typeof window == void 0 && typeof exports == "object" ) {
exports . Suite = jasmineRequire . Suite ;
}
getJasmineRequireObj ( ) . Timer = function ( ) {
function Timer ( options ) {
options = options || { } ;
var now = options . now || function ( ) { return new Date ( ) . getTime ( ) ; } ,
startTime ;
this . start = function ( ) {
startTime = now ( ) ;
} ;
this . elapsed = function ( ) {
return now ( ) - startTime ;
} ;
}
return Timer ;
} ;
2013-10-31 02:00:50 +08:00
2013-10-25 11:16:14 +08:00
getJasmineRequireObj ( ) . matchersUtil = function ( j$ ) {
// TODO: what to do about jasmine.pp not being inject? move to JSON.stringify? gut PrettyPrinter?
return {
equals : function ( a , b , customTesters ) {
customTesters = customTesters || [ ] ;
return eq ( a , b , [ ] , [ ] , customTesters ) ;
} ,
contains : function ( haystack , needle , customTesters ) {
customTesters = customTesters || [ ] ;
if ( Object . prototype . toString . apply ( haystack ) === "[object Array]" ) {
for ( var i = 0 ; i < haystack . length ; i ++ ) {
if ( eq ( haystack [ i ] , needle , [ ] , [ ] , customTesters ) ) {
return true ;
}
}
return false ;
}
return haystack . indexOf ( needle ) >= 0 ;
} ,
buildFailureMessage : function ( ) {
var args = Array . prototype . slice . call ( arguments , 0 ) ,
matcherName = args [ 0 ] ,
isNot = args [ 1 ] ,
actual = args [ 2 ] ,
expected = args . slice ( 3 ) ,
englishyPredicate = matcherName . replace ( /[A-Z]/g , function ( s ) { return ' ' + s . toLowerCase ( ) ; } ) ;
var message = "Expected " +
j$ . pp ( actual ) +
( isNot ? " not " : " " ) +
englishyPredicate ;
if ( expected . length > 0 ) {
for ( var i = 0 ; i < expected . length ; i ++ ) {
2013-10-31 02:00:50 +08:00
if ( i > 0 ) {
message += "," ;
}
2013-10-25 11:16:14 +08:00
message += " " + j$ . pp ( expected [ i ] ) ;
}
}
return message + "." ;
}
} ;
// Equality function lovingly adapted from isEqual in
// [Underscore](http://underscorejs.org)
function eq ( a , b , aStack , bStack , customTesters ) {
var result = true ;
for ( var i = 0 ; i < customTesters . length ; i ++ ) {
2013-10-31 02:00:50 +08:00
var customTesterResult = customTesters [ i ] ( a , b ) ;
if ( ! j$ . util . isUndefined ( customTesterResult ) ) {
return customTesterResult ;
2013-10-25 11:16:14 +08:00
}
}
if ( a instanceof j$ . Any ) {
result = a . jasmineMatches ( b ) ;
if ( result ) {
return true ;
}
}
if ( b instanceof j$ . Any ) {
result = b . jasmineMatches ( a ) ;
if ( result ) {
return true ;
}
}
if ( b instanceof j$ . ObjectContaining ) {
result = b . jasmineMatches ( a ) ;
if ( result ) {
return true ;
}
}
if ( a instanceof Error && b instanceof Error ) {
return a . message == b . message ;
}
// Identical objects are equal. `0 === -0`, but they aren't identical.
// See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
2013-10-31 02:00:50 +08:00
if ( a === b ) { return a !== 0 || 1 / a == 1 / b ; }
2013-10-25 11:16:14 +08:00
// A strict comparison is necessary because `null == undefined`.
2013-10-31 02:00:50 +08:00
if ( a === null || b === null ) { return a === b ; }
2013-10-25 11:16:14 +08:00
var className = Object . prototype . toString . call ( a ) ;
2013-10-31 02:00:50 +08:00
if ( className != Object . prototype . toString . call ( b ) ) { return false ; }
2013-10-25 11:16:14 +08:00
switch ( className ) {
// Strings, numbers, dates, and booleans are compared by value.
case '[object String]' :
// Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
// equivalent to `new String("5")`.
return a == String ( b ) ;
case '[object Number]' :
// `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for
// other numeric values.
return a != + a ? b != + b : ( a === 0 ? 1 / a == 1 / b : a == + b ) ;
case '[object Date]' :
case '[object Boolean]' :
// Coerce dates and booleans to numeric primitive values. Dates are compared by their
// millisecond representations. Note that invalid dates with millisecond representations
// of `NaN` are not equivalent.
return + a == + b ;
// RegExps are compared by their source patterns and flags.
case '[object RegExp]' :
return a . source == b . source &&
a . global == b . global &&
a . multiline == b . multiline &&
a . ignoreCase == b . ignoreCase ;
}
2013-10-31 02:00:50 +08:00
if ( typeof a != 'object' || typeof b != 'object' ) { return false ; }
2013-10-25 11:16:14 +08:00
// Assume equality for cyclic structures. The algorithm for detecting cyclic
// structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
var length = aStack . length ;
while ( length -- ) {
// Linear search. Performance is inversely proportional to the number of
// unique nested structures.
2013-10-31 02:00:50 +08:00
if ( aStack [ length ] == a ) { return bStack [ length ] == b ; }
2013-10-25 11:16:14 +08:00
}
// Add the first object to the stack of traversed objects.
aStack . push ( a ) ;
bStack . push ( b ) ;
var size = 0 ;
// Recursively compare objects and arrays.
if ( className == '[object Array]' ) {
// Compare array lengths to determine if a deep comparison is necessary.
size = a . length ;
result = size == b . length ;
if ( result ) {
// Deep compare the contents, ignoring non-numeric properties.
while ( size -- ) {
2013-10-31 02:00:50 +08:00
if ( ! ( result = eq ( a [ size ] , b [ size ] , aStack , bStack , customTesters ) ) ) { break ; }
2013-10-25 11:16:14 +08:00
}
}
} else {
// Objects with different constructors are not equivalent, but `Object`s
// from different frames are.
var aCtor = a . constructor , bCtor = b . constructor ;
if ( aCtor !== bCtor && ! ( isFunction ( aCtor ) && ( aCtor instanceof aCtor ) &&
isFunction ( bCtor ) && ( bCtor instanceof bCtor ) ) ) {
return false ;
}
// Deep compare objects.
for ( var key in a ) {
if ( has ( a , key ) ) {
// Count the expected number of properties.
size ++ ;
// Deep compare each member.
2013-10-31 02:00:50 +08:00
if ( ! ( result = has ( b , key ) && eq ( a [ key ] , b [ key ] , aStack , bStack , customTesters ) ) ) { break ; }
2013-10-25 11:16:14 +08:00
}
}
// Ensure that both objects contain the same number of properties.
if ( result ) {
for ( key in b ) {
2013-10-31 02:00:50 +08:00
if ( has ( b , key ) && ! ( size -- ) ) { break ; }
2013-10-25 11:16:14 +08:00
}
result = ! size ;
}
}
// Remove the first object from the stack of traversed objects.
aStack . pop ( ) ;
bStack . pop ( ) ;
return result ;
function has ( obj , key ) {
return obj . hasOwnProperty ( key ) ;
}
function isFunction ( obj ) {
return typeof obj === 'function' ;
}
}
} ;
2013-10-31 02:00:50 +08:00
2013-10-25 11:16:14 +08:00
getJasmineRequireObj ( ) . toBe = function ( ) {
function toBe ( ) {
return {
compare : function ( actual , expected ) {
return {
pass : actual === expected
} ;
}
} ;
}
return toBe ;
} ;
getJasmineRequireObj ( ) . toBeCloseTo = function ( ) {
function toBeCloseTo ( ) {
return {
compare : function ( actual , expected , precision ) {
if ( precision !== 0 ) {
precision = precision || 2 ;
}
return {
pass : Math . abs ( expected - actual ) < ( Math . pow ( 10 , - precision ) / 2 )
} ;
}
} ;
}
return toBeCloseTo ;
} ;
getJasmineRequireObj ( ) . toBeDefined = function ( ) {
function toBeDefined ( ) {
return {
compare : function ( actual ) {
return {
pass : ( void 0 !== actual )
} ;
}
} ;
}
return toBeDefined ;
} ;
getJasmineRequireObj ( ) . toBeFalsy = function ( ) {
function toBeFalsy ( ) {
return {
compare : function ( actual ) {
return {
pass : ! ! ! actual
} ;
}
} ;
}
return toBeFalsy ;
} ;
getJasmineRequireObj ( ) . toBeGreaterThan = function ( ) {
function toBeGreaterThan ( ) {
return {
compare : function ( actual , expected ) {
return {
pass : actual > expected
} ;
}
} ;
}
return toBeGreaterThan ;
} ;
getJasmineRequireObj ( ) . toBeLessThan = function ( ) {
function toBeLessThan ( ) {
return {
compare : function ( actual , expected ) {
return {
pass : actual < expected
} ;
}
} ;
}
return toBeLessThan ;
} ;
getJasmineRequireObj ( ) . toBeNaN = function ( j$ ) {
function toBeNaN ( ) {
return {
compare : function ( actual ) {
var result = {
pass : ( actual !== actual )
} ;
if ( result . pass ) {
result . message = "Expected actual not to be NaN." ;
} else {
result . message = "Expected " + j$ . pp ( actual ) + " to be NaN." ;
}
return result ;
}
} ;
}
return toBeNaN ;
} ;
getJasmineRequireObj ( ) . toBeNull = function ( ) {
function toBeNull ( ) {
return {
compare : function ( actual ) {
return {
pass : actual === null
} ;
}
} ;
}
return toBeNull ;
} ;
getJasmineRequireObj ( ) . toBeTruthy = function ( ) {
function toBeTruthy ( ) {
return {
compare : function ( actual ) {
return {
pass : ! ! actual
} ;
}
} ;
}
return toBeTruthy ;
} ;
getJasmineRequireObj ( ) . toBeUndefined = function ( ) {
function toBeUndefined ( ) {
return {
compare : function ( actual ) {
return {
pass : void 0 === actual
} ;
}
} ;
}
return toBeUndefined ;
} ;
getJasmineRequireObj ( ) . toContain = function ( ) {
function toContain ( util , customEqualityTesters ) {
customEqualityTesters = customEqualityTesters || [ ] ;
return {
compare : function ( actual , expected ) {
return {
pass : util . contains ( actual , expected , customEqualityTesters )
} ;
}
} ;
}
return toContain ;
} ;
getJasmineRequireObj ( ) . toEqual = function ( ) {
function toEqual ( util , customEqualityTesters ) {
customEqualityTesters = customEqualityTesters || [ ] ;
return {
compare : function ( actual , expected ) {
var result = {
pass : false
} ;
result . pass = util . equals ( actual , expected , customEqualityTesters ) ;
return result ;
}
} ;
}
return toEqual ;
} ;
getJasmineRequireObj ( ) . toHaveBeenCalled = function ( j$ ) {
function toHaveBeenCalled ( ) {
return {
compare : function ( actual ) {
var result = { } ;
if ( ! j$ . isSpy ( actual ) ) {
throw new Error ( 'Expected a spy, but got ' + j$ . pp ( actual ) + '.' ) ;
}
if ( arguments . length > 1 ) {
throw new Error ( 'toHaveBeenCalled does not take arguments, use toHaveBeenCalledWith' ) ;
}
result . pass = actual . calls . any ( ) ;
result . message = result . pass ?
"Expected spy " + actual . and . identity ( ) + " not to have been called." :
"Expected spy " + actual . and . identity ( ) + " to have been called." ;
return result ;
}
} ;
}
return toHaveBeenCalled ;
} ;
getJasmineRequireObj ( ) . toHaveBeenCalledWith = function ( j$ ) {
function toHaveBeenCalledWith ( util ) {
return {
compare : function ( ) {
var args = Array . prototype . slice . call ( arguments , 0 ) ,
actual = args [ 0 ] ,
expectedArgs = args . slice ( 1 ) ,
result = { pass : false } ;
if ( ! j$ . isSpy ( actual ) ) {
throw new Error ( 'Expected a spy, but got ' + j$ . pp ( actual ) + '.' ) ;
}
if ( ! actual . calls . any ( ) ) {
result . message = "Expected spy " + actual . and . identity ( ) + " to have been called with " + j$ . pp ( expectedArgs ) + " but it was never called." ;
return result ;
}
if ( util . contains ( actual . calls . allArgs ( ) , expectedArgs ) ) {
result . pass = true ;
result . message = "Expected spy " + actual . and . identity ( ) + " not to have been called with " + j$ . pp ( expectedArgs ) + " but it was." ;
} else {
result . message = "Expected spy " + actual . and . identity ( ) + " to have been called with " + j$ . pp ( expectedArgs ) + " but actual calls were " + j$ . pp ( actual . calls . allArgs ( ) ) . replace ( /^\[ | \]$/g , '' ) + "." ;
}
return result ;
}
} ;
}
return toHaveBeenCalledWith ;
} ;
getJasmineRequireObj ( ) . toMatch = function ( ) {
function toMatch ( ) {
return {
compare : function ( actual , expected ) {
var regexp = new RegExp ( expected ) ;
return {
pass : regexp . test ( actual )
} ;
}
} ;
}
return toMatch ;
} ;
getJasmineRequireObj ( ) . toThrow = function ( j$ ) {
function toThrow ( util ) {
return {
compare : function ( actual , expected ) {
var result = { pass : false } ,
threw = false ,
thrown ;
if ( typeof actual != "function" ) {
throw new Error ( "Actual is not a Function" ) ;
}
try {
actual ( ) ;
} catch ( e ) {
threw = true ;
thrown = e ;
}
if ( ! threw ) {
result . message = "Expected function to throw an exception." ;
return result ;
}
if ( arguments . length == 1 ) {
result . pass = true ;
result . message = "Expected function not to throw, but it threw " + j$ . pp ( thrown ) + "." ;
return result ;
}
if ( util . equals ( thrown , expected ) ) {
result . pass = true ;
result . message = "Expected function not to throw " + j$ . pp ( expected ) + "." ;
} else {
result . message = "Expected function to throw " + j$ . pp ( expected ) + ", but it threw " + j$ . pp ( thrown ) + "." ;
}
return result ;
}
} ;
}
return toThrow ;
} ;
getJasmineRequireObj ( ) . toThrowError = function ( j$ ) {
function toThrowError ( util ) {
return {
compare : function ( actual ) {
var threw = false ,
thrown ,
errorType ,
message ,
regexp ,
name ,
constructorName ;
if ( typeof actual != "function" ) {
throw new Error ( "Actual is not a Function" ) ;
}
extractExpectedParams . apply ( null , arguments ) ;
try {
actual ( ) ;
} catch ( e ) {
threw = true ;
thrown = e ;
}
if ( ! threw ) {
return fail ( "Expected function to throw an Error." ) ;
}
if ( ! ( thrown instanceof Error ) ) {
return fail ( "Expected function to throw an Error, but it threw " + thrown + "." ) ;
}
if ( arguments . length == 1 ) {
return pass ( "Expected function not to throw an Error, but it threw " + fnNameFor ( thrown ) + "." ) ;
}
if ( errorType ) {
name = fnNameFor ( errorType ) ;
constructorName = fnNameFor ( thrown . constructor ) ;
}
if ( errorType && message ) {
if ( thrown . constructor == errorType && util . equals ( thrown . message , message ) ) {
return pass ( "Expected function not to throw " + name + " with message \"" + message + "\"." ) ;
} else {
return fail ( "Expected function to throw " + name + " with message \"" + message +
"\", but it threw " + constructorName + " with message \"" + thrown . message + "\"." ) ;
}
}
if ( errorType && regexp ) {
if ( thrown . constructor == errorType && regexp . test ( thrown . message ) ) {
return pass ( "Expected function not to throw " + name + " with message matching " + regexp + "." ) ;
} else {
return fail ( "Expected function to throw " + name + " with message matching " + regexp +
", but it threw " + constructorName + " with message \"" + thrown . message + "\"." ) ;
}
}
if ( errorType ) {
if ( thrown . constructor == errorType ) {
return pass ( "Expected function not to throw " + name + "." ) ;
} else {
return fail ( "Expected function to throw " + name + ", but it threw " + constructorName + "." ) ;
}
}
if ( message ) {
if ( thrown . message == message ) {
return pass ( "Expected function not to throw an exception with message " + j$ . pp ( message ) + "." ) ;
} else {
return fail ( "Expected function to throw an exception with message " + j$ . pp ( message ) +
", but it threw an exception with message " + j$ . pp ( thrown . message ) + "." ) ;
}
}
if ( regexp ) {
if ( regexp . test ( thrown . message ) ) {
return pass ( "Expected function not to throw an exception with a message matching " + j$ . pp ( regexp ) + "." ) ;
} else {
return fail ( "Expected function to throw an exception with a message matching " + j$ . pp ( regexp ) +
", but it threw an exception with message " + j$ . pp ( thrown . message ) + "." ) ;
}
}
function fnNameFor ( func ) {
return func . name || func . toString ( ) . match ( /^\s*function\s*(\w*)\s*\(/ ) [ 1 ] ;
}
function pass ( notMessage ) {
return {
pass : true ,
message : notMessage
} ;
}
function fail ( message ) {
return {
pass : false ,
message : message
} ;
}
function extractExpectedParams ( ) {
if ( arguments . length == 1 ) {
return ;
}
if ( arguments . length == 2 ) {
var expected = arguments [ 1 ] ;
if ( expected instanceof RegExp ) {
regexp = expected ;
} else if ( typeof expected == "string" ) {
message = expected ;
} else if ( checkForAnErrorType ( expected ) ) {
errorType = expected ;
}
if ( ! ( errorType || message || regexp ) ) {
throw new Error ( "Expected is not an Error, string, or RegExp." ) ;
}
} else {
if ( checkForAnErrorType ( arguments [ 1 ] ) ) {
errorType = arguments [ 1 ] ;
} else {
throw new Error ( "Expected error type is not an Error." ) ;
}
if ( arguments [ 2 ] instanceof RegExp ) {
regexp = arguments [ 2 ] ;
} else if ( typeof arguments [ 2 ] == "string" ) {
message = arguments [ 2 ] ;
} else {
throw new Error ( "Expected error message is not a string or RegExp." ) ;
}
}
}
function checkForAnErrorType ( type ) {
if ( typeof type !== "function" ) {
return false ;
}
var Surrogate = function ( ) { } ;
Surrogate . prototype = type . prototype ;
return ( new Surrogate ( ) ) instanceof Error ;
}
}
} ;
}
return toThrowError ;
} ;
getJasmineRequireObj ( ) . version = function ( ) {
2013-10-31 02:00:50 +08:00
return "2.0.0-rc5" ;
} ;