github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/public/libs/vue-1.0.24/test/unit/lib/jasmine.js (about) 1 /* 2 Copyright (c) 2008-2014 Pivotal Labs 3 4 Permission is hereby granted, free of charge, to any person obtaining 5 a copy of this software and associated documentation files (the 6 "Software"), to deal in the Software without restriction, including 7 without limitation the rights to use, copy, modify, merge, publish, 8 distribute, sublicense, and/or sell copies of the Software, and to 9 permit persons to whom the Software is furnished to do so, subject to 10 the following conditions: 11 12 The above copyright notice and this permission notice shall be 13 included in all copies or substantial portions of the Software. 14 15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 */ 23 function getJasmineRequireObj() { 24 if (typeof module !== 'undefined' && module.exports) { 25 return exports; 26 } else { 27 window.jasmineRequire = window.jasmineRequire || {}; 28 return window.jasmineRequire; 29 } 30 } 31 32 getJasmineRequireObj().core = function(jRequire) { 33 var j$ = {}; 34 35 jRequire.base(j$); 36 j$.util = jRequire.util(); 37 j$.Any = jRequire.Any(); 38 j$.CallTracker = jRequire.CallTracker(); 39 j$.MockDate = jRequire.MockDate(); 40 j$.Clock = jRequire.Clock(); 41 j$.DelayedFunctionScheduler = jRequire.DelayedFunctionScheduler(); 42 j$.Env = jRequire.Env(j$); 43 j$.ExceptionFormatter = jRequire.ExceptionFormatter(); 44 j$.Expectation = jRequire.Expectation(); 45 j$.buildExpectationResult = jRequire.buildExpectationResult(); 46 j$.JsApiReporter = jRequire.JsApiReporter(); 47 j$.matchersUtil = jRequire.matchersUtil(j$); 48 j$.ObjectContaining = jRequire.ObjectContaining(j$); 49 j$.pp = jRequire.pp(j$); 50 j$.QueueRunner = jRequire.QueueRunner(j$); 51 j$.ReportDispatcher = jRequire.ReportDispatcher(); 52 j$.Spec = jRequire.Spec(j$); 53 j$.SpyStrategy = jRequire.SpyStrategy(); 54 j$.Suite = jRequire.Suite(); 55 j$.Timer = jRequire.Timer(); 56 j$.version = jRequire.version(); 57 58 j$.matchers = jRequire.requireMatchers(jRequire, j$); 59 60 return j$; 61 }; 62 63 getJasmineRequireObj().requireMatchers = function(jRequire, j$) { 64 var availableMatchers = [ 65 'toBe', 66 'toBeCloseTo', 67 'toBeDefined', 68 'toBeFalsy', 69 'toBeGreaterThan', 70 'toBeLessThan', 71 'toBeNaN', 72 'toBeNull', 73 'toBeTruthy', 74 'toBeUndefined', 75 'toContain', 76 'toEqual', 77 'toHaveBeenCalled', 78 'toHaveBeenCalledWith', 79 'toMatch', 80 'toThrow', 81 'toThrowError' 82 ], 83 matchers = {}; 84 85 for (var i = 0; i < availableMatchers.length; i++) { 86 var name = availableMatchers[i]; 87 matchers[name] = jRequire[name](j$); 88 } 89 90 return matchers; 91 }; 92 93 getJasmineRequireObj().base = (function (jasmineGlobal) { 94 if (typeof module !== 'undefined' && module.exports) { 95 jasmineGlobal = global; 96 } 97 98 return function(j$) { 99 j$.unimplementedMethod_ = function() { 100 throw new Error('unimplemented method'); 101 }; 102 103 j$.MAX_PRETTY_PRINT_DEPTH = 40; 104 j$.MAX_PRETTY_PRINT_ARRAY_LENGTH = 100; 105 j$.DEFAULT_TIMEOUT_INTERVAL = 5000; 106 107 j$.getGlobal = function() { 108 return jasmineGlobal; 109 }; 110 111 j$.getEnv = function(options) { 112 var env = j$.currentEnv_ = j$.currentEnv_ || new j$.Env(options); 113 //jasmine. singletons in here (setTimeout blah blah). 114 return env; 115 }; 116 117 j$.isArray_ = function(value) { 118 return j$.isA_('Array', value); 119 }; 120 121 j$.isString_ = function(value) { 122 return j$.isA_('String', value); 123 }; 124 125 j$.isNumber_ = function(value) { 126 return j$.isA_('Number', value); 127 }; 128 129 j$.isA_ = function(typeName, value) { 130 return Object.prototype.toString.apply(value) === '[object ' + typeName + ']'; 131 }; 132 133 j$.isDomNode = function(obj) { 134 return obj.nodeType > 0; 135 }; 136 137 j$.any = function(clazz) { 138 return new j$.Any(clazz); 139 }; 140 141 j$.objectContaining = function(sample) { 142 return new j$.ObjectContaining(sample); 143 }; 144 145 j$.createSpy = function(name, originalFn) { 146 147 var spyStrategy = new j$.SpyStrategy({ 148 name: name, 149 fn: originalFn, 150 getSpy: function() { return spy; } 151 }), 152 callTracker = new j$.CallTracker(), 153 spy = function() { 154 callTracker.track({ 155 object: this, 156 args: Array.prototype.slice.apply(arguments) 157 }); 158 return spyStrategy.exec.apply(this, arguments); 159 }; 160 161 for (var prop in originalFn) { 162 if (prop === 'and' || prop === 'calls') { 163 throw new Error('Jasmine spies would overwrite the \'and\' and \'calls\' properties on the object being spied upon'); 164 } 165 166 spy[prop] = originalFn[prop]; 167 } 168 169 spy.and = spyStrategy; 170 spy.calls = callTracker; 171 172 return spy; 173 }; 174 175 j$.isSpy = function(putativeSpy) { 176 if (!putativeSpy) { 177 return false; 178 } 179 return putativeSpy.and instanceof j$.SpyStrategy && 180 putativeSpy.calls instanceof j$.CallTracker; 181 }; 182 183 j$.createSpyObj = function(baseName, methodNames) { 184 if (!j$.isArray_(methodNames) || methodNames.length === 0) { 185 throw 'createSpyObj requires a non-empty array of method names to create spies for'; 186 } 187 var obj = {}; 188 for (var i = 0; i < methodNames.length; i++) { 189 obj[methodNames[i]] = j$.createSpy(baseName + '.' + methodNames[i]); 190 } 191 return obj; 192 }; 193 }; 194 })(this); 195 196 getJasmineRequireObj().util = function() { 197 198 var util = {}; 199 200 util.inherit = function(childClass, parentClass) { 201 var Subclass = function() { 202 }; 203 Subclass.prototype = parentClass.prototype; 204 childClass.prototype = new Subclass(); 205 }; 206 207 util.htmlEscape = function(str) { 208 if (!str) { 209 return str; 210 } 211 return str.replace(/&/g, '&') 212 .replace(/</g, '<') 213 .replace(/>/g, '>'); 214 }; 215 216 util.argsToArray = function(args) { 217 var arrayOfArgs = []; 218 for (var i = 0; i < args.length; i++) { 219 arrayOfArgs.push(args[i]); 220 } 221 return arrayOfArgs; 222 }; 223 224 util.isUndefined = function(obj) { 225 return obj === void 0; 226 }; 227 228 util.arrayContains = function(array, search) { 229 var i = array.length; 230 while (i--) { 231 if (array[i] == search) { 232 return true; 233 } 234 } 235 return false; 236 }; 237 238 return util; 239 }; 240 241 getJasmineRequireObj().Spec = function(j$) { 242 function Spec(attrs) { 243 this.expectationFactory = attrs.expectationFactory; 244 this.resultCallback = attrs.resultCallback || function() {}; 245 this.id = attrs.id; 246 this.description = attrs.description || ''; 247 this.fn = attrs.fn; 248 this.beforeFns = attrs.beforeFns || function() { return []; }; 249 this.afterFns = attrs.afterFns || function() { return []; }; 250 this.onStart = attrs.onStart || function() {}; 251 this.exceptionFormatter = attrs.exceptionFormatter || function() {}; 252 this.getSpecName = attrs.getSpecName || function() { return ''; }; 253 this.expectationResultFactory = attrs.expectationResultFactory || function() { }; 254 this.queueRunnerFactory = attrs.queueRunnerFactory || function() {}; 255 this.catchingExceptions = attrs.catchingExceptions || function() { return true; }; 256 257 if (!this.fn) { 258 this.pend(); 259 } 260 261 this.result = { 262 id: this.id, 263 description: this.description, 264 fullName: this.getFullName(), 265 failedExpectations: [], 266 passedExpectations: [] 267 }; 268 } 269 270 Spec.prototype.addExpectationResult = function(passed, data) { 271 var expectationResult = this.expectationResultFactory(data); 272 if (passed) { 273 this.result.passedExpectations.push(expectationResult); 274 } else { 275 this.result.failedExpectations.push(expectationResult); 276 } 277 }; 278 279 Spec.prototype.expect = function(actual) { 280 return this.expectationFactory(actual, this); 281 }; 282 283 Spec.prototype.execute = function(onComplete) { 284 var self = this; 285 286 this.onStart(this); 287 288 if (this.markedPending || this.disabled) { 289 complete(); 290 return; 291 } 292 293 var allFns = this.beforeFns().concat(this.fn).concat(this.afterFns()); 294 295 this.queueRunnerFactory({ 296 fns: allFns, 297 onException: onException, 298 onComplete: complete, 299 enforceTimeout: function() { return true; } 300 }); 301 302 function onException(e) { 303 if (Spec.isPendingSpecException(e)) { 304 self.pend(); 305 return; 306 } 307 308 self.addExpectationResult(false, { 309 matcherName: '', 310 passed: false, 311 expected: '', 312 actual: '', 313 error: e 314 }); 315 } 316 317 function complete() { 318 self.result.status = self.status(); 319 self.resultCallback(self.result); 320 321 if (onComplete) { 322 onComplete(); 323 } 324 } 325 }; 326 327 Spec.prototype.disable = function() { 328 this.disabled = true; 329 }; 330 331 Spec.prototype.pend = function() { 332 this.markedPending = true; 333 }; 334 335 Spec.prototype.status = function() { 336 if (this.disabled) { 337 return 'disabled'; 338 } 339 340 if (this.markedPending) { 341 return 'pending'; 342 } 343 344 if (this.result.failedExpectations.length > 0) { 345 return 'failed'; 346 } else { 347 return 'passed'; 348 } 349 }; 350 351 Spec.prototype.getFullName = function() { 352 return this.getSpecName(this); 353 }; 354 355 Spec.pendingSpecExceptionMessage = '=> marked Pending'; 356 357 Spec.isPendingSpecException = function(e) { 358 return !!(e && e.toString && e.toString().indexOf(Spec.pendingSpecExceptionMessage) !== -1); 359 }; 360 361 return Spec; 362 }; 363 364 if (typeof window == void 0 && typeof exports == 'object') { 365 exports.Spec = jasmineRequire.Spec; 366 } 367 368 getJasmineRequireObj().Env = function(j$) { 369 function Env(options) { 370 options = options || {}; 371 372 var self = this; 373 var global = options.global || j$.getGlobal(); 374 375 var totalSpecsDefined = 0; 376 377 var catchExceptions = true; 378 379 var realSetTimeout = j$.getGlobal().setTimeout; 380 var realClearTimeout = j$.getGlobal().clearTimeout; 381 this.clock = new j$.Clock(global, new j$.DelayedFunctionScheduler(), new j$.MockDate(global)); 382 383 var runnableLookupTable = {}; 384 385 var spies = []; 386 387 var currentSpec = null; 388 var currentSuite = null; 389 390 var reporter = new j$.ReportDispatcher([ 391 'jasmineStarted', 392 'jasmineDone', 393 'suiteStarted', 394 'suiteDone', 395 'specStarted', 396 'specDone' 397 ]); 398 399 this.specFilter = function() { 400 return true; 401 }; 402 403 var equalityTesters = []; 404 405 var customEqualityTesters = []; 406 this.addCustomEqualityTester = function(tester) { 407 customEqualityTesters.push(tester); 408 }; 409 410 j$.Expectation.addCoreMatchers(j$.matchers); 411 412 var nextSpecId = 0; 413 var getNextSpecId = function() { 414 return 'spec' + nextSpecId++; 415 }; 416 417 var nextSuiteId = 0; 418 var getNextSuiteId = function() { 419 return 'suite' + nextSuiteId++; 420 }; 421 422 var expectationFactory = function(actual, spec) { 423 return j$.Expectation.Factory({ 424 util: j$.matchersUtil, 425 customEqualityTesters: customEqualityTesters, 426 actual: actual, 427 addExpectationResult: addExpectationResult 428 }); 429 430 function addExpectationResult(passed, result) { 431 return spec.addExpectationResult(passed, result); 432 } 433 }; 434 435 var specStarted = function(spec) { 436 currentSpec = spec; 437 reporter.specStarted(spec.result); 438 }; 439 440 var beforeFns = function(suite) { 441 return function() { 442 var befores = []; 443 while(suite) { 444 befores = befores.concat(suite.beforeFns); 445 suite = suite.parentSuite; 446 } 447 return befores.reverse(); 448 }; 449 }; 450 451 var afterFns = function(suite) { 452 return function() { 453 var afters = []; 454 while(suite) { 455 afters = afters.concat(suite.afterFns); 456 suite = suite.parentSuite; 457 } 458 return afters; 459 }; 460 }; 461 462 var getSpecName = function(spec, suite) { 463 return suite.getFullName() + ' ' + spec.description; 464 }; 465 466 // TODO: we may just be able to pass in the fn instead of wrapping here 467 var buildExpectationResult = j$.buildExpectationResult, 468 exceptionFormatter = new j$.ExceptionFormatter(), 469 expectationResultFactory = function(attrs) { 470 attrs.messageFormatter = exceptionFormatter.message; 471 attrs.stackFormatter = exceptionFormatter.stack; 472 473 return buildExpectationResult(attrs); 474 }; 475 476 // TODO: fix this naming, and here's where the value comes in 477 this.catchExceptions = function(value) { 478 catchExceptions = !!value; 479 return catchExceptions; 480 }; 481 482 this.catchingExceptions = function() { 483 return catchExceptions; 484 }; 485 486 var maximumSpecCallbackDepth = 20; 487 var currentSpecCallbackDepth = 0; 488 489 function clearStack(fn) { 490 currentSpecCallbackDepth++; 491 if (currentSpecCallbackDepth >= maximumSpecCallbackDepth) { 492 currentSpecCallbackDepth = 0; 493 realSetTimeout(fn, 0); 494 } else { 495 fn(); 496 } 497 } 498 499 var catchException = function(e) { 500 return j$.Spec.isPendingSpecException(e) || catchExceptions; 501 }; 502 503 var queueRunnerFactory = function(options) { 504 options.catchException = catchException; 505 options.clearStack = options.clearStack || clearStack; 506 options.timer = {setTimeout: realSetTimeout, clearTimeout: realClearTimeout}; 507 508 new j$.QueueRunner(options).execute(); 509 }; 510 511 var topSuite = new j$.Suite({ 512 env: this, 513 id: getNextSuiteId(), 514 description: 'Jasmine__TopLevel__Suite', 515 queueRunner: queueRunnerFactory, 516 resultCallback: function() {} // TODO - hook this up 517 }); 518 runnableLookupTable[topSuite.id] = topSuite; 519 currentSuite = topSuite; 520 521 this.topSuite = function() { 522 return topSuite; 523 }; 524 525 this.execute = function(runnablesToRun) { 526 runnablesToRun = runnablesToRun || [topSuite.id]; 527 528 var allFns = []; 529 for(var i = 0; i < runnablesToRun.length; i++) { 530 var runnable = runnableLookupTable[runnablesToRun[i]]; 531 allFns.push((function(runnable) { return function(done) { runnable.execute(done); }; })(runnable)); 532 } 533 534 reporter.jasmineStarted({ 535 totalSpecsDefined: totalSpecsDefined 536 }); 537 538 queueRunnerFactory({fns: allFns, onComplete: reporter.jasmineDone}); 539 }; 540 541 this.addReporter = function(reporterToAdd) { 542 reporter.addReporter(reporterToAdd); 543 }; 544 545 this.addMatchers = function(matchersToAdd) { 546 j$.Expectation.addMatchers(matchersToAdd); 547 }; 548 549 this.spyOn = function(obj, methodName) { 550 if (j$.util.isUndefined(obj)) { 551 throw new Error('spyOn could not find an object to spy upon for ' + methodName + '()'); 552 } 553 554 if (j$.util.isUndefined(obj[methodName])) { 555 throw new Error(methodName + '() method does not exist'); 556 } 557 558 if (obj[methodName] && j$.isSpy(obj[methodName])) { 559 //TODO?: should this return the current spy? Downside: may cause user confusion about spy state 560 throw new Error(methodName + ' has already been spied upon'); 561 } 562 563 var spy = j$.createSpy(methodName, obj[methodName]); 564 565 spies.push({ 566 spy: spy, 567 baseObj: obj, 568 methodName: methodName, 569 originalValue: obj[methodName] 570 }); 571 572 obj[methodName] = spy; 573 574 return spy; 575 }; 576 577 var suiteFactory = function(description) { 578 var suite = new j$.Suite({ 579 env: self, 580 id: getNextSuiteId(), 581 description: description, 582 parentSuite: currentSuite, 583 queueRunner: queueRunnerFactory, 584 onStart: suiteStarted, 585 resultCallback: function(attrs) { 586 reporter.suiteDone(attrs); 587 } 588 }); 589 590 runnableLookupTable[suite.id] = suite; 591 return suite; 592 }; 593 594 this.describe = function(description, specDefinitions) { 595 var suite = suiteFactory(description); 596 597 var parentSuite = currentSuite; 598 parentSuite.addChild(suite); 599 currentSuite = suite; 600 601 var declarationError = null; 602 try { 603 specDefinitions.call(suite); 604 } catch (e) { 605 declarationError = e; 606 } 607 608 if (declarationError) { 609 this.it('encountered a declaration exception', function() { 610 throw declarationError; 611 }); 612 } 613 614 currentSuite = parentSuite; 615 616 return suite; 617 }; 618 619 this.xdescribe = function(description, specDefinitions) { 620 var suite = this.describe(description, specDefinitions); 621 suite.disable(); 622 return suite; 623 }; 624 625 var specFactory = function(description, fn, suite) { 626 totalSpecsDefined++; 627 628 var spec = new j$.Spec({ 629 id: getNextSpecId(), 630 beforeFns: beforeFns(suite), 631 afterFns: afterFns(suite), 632 expectationFactory: expectationFactory, 633 exceptionFormatter: exceptionFormatter, 634 resultCallback: specResultCallback, 635 getSpecName: function(spec) { 636 return getSpecName(spec, suite); 637 }, 638 onStart: specStarted, 639 description: description, 640 expectationResultFactory: expectationResultFactory, 641 queueRunnerFactory: queueRunnerFactory, 642 fn: fn 643 }); 644 645 runnableLookupTable[spec.id] = spec; 646 647 if (!self.specFilter(spec)) { 648 spec.disable(); 649 } 650 651 return spec; 652 653 function removeAllSpies() { 654 for (var i = 0; i < spies.length; i++) { 655 var spyEntry = spies[i]; 656 spyEntry.baseObj[spyEntry.methodName] = spyEntry.originalValue; 657 } 658 spies = []; 659 } 660 661 function specResultCallback(result) { 662 removeAllSpies(); 663 j$.Expectation.resetMatchers(); 664 customEqualityTesters = []; 665 currentSpec = null; 666 reporter.specDone(result); 667 } 668 }; 669 670 var suiteStarted = function(suite) { 671 reporter.suiteStarted(suite.result); 672 }; 673 674 this.it = function(description, fn) { 675 var spec = specFactory(description, fn, currentSuite); 676 currentSuite.addChild(spec); 677 return spec; 678 }; 679 680 this.xit = function(description, fn) { 681 var spec = this.it(description, fn); 682 spec.pend(); 683 return spec; 684 }; 685 686 this.expect = function(actual) { 687 if (!currentSpec) { 688 throw new Error('\'expect\' was used when there was no current spec, this could be because an asynchronous test timed out'); 689 } 690 691 return currentSpec.expect(actual); 692 }; 693 694 this.beforeEach = function(beforeEachFunction) { 695 currentSuite.beforeEach(beforeEachFunction); 696 }; 697 698 this.afterEach = function(afterEachFunction) { 699 currentSuite.afterEach(afterEachFunction); 700 }; 701 702 this.pending = function() { 703 throw j$.Spec.pendingSpecExceptionMessage; 704 }; 705 } 706 707 return Env; 708 }; 709 710 getJasmineRequireObj().JsApiReporter = function() { 711 712 var noopTimer = { 713 start: function(){}, 714 elapsed: function(){ return 0; } 715 }; 716 717 function JsApiReporter(options) { 718 var timer = options.timer || noopTimer, 719 status = 'loaded'; 720 721 this.started = false; 722 this.finished = false; 723 724 this.jasmineStarted = function() { 725 this.started = true; 726 status = 'started'; 727 timer.start(); 728 }; 729 730 var executionTime; 731 732 this.jasmineDone = function() { 733 this.finished = true; 734 executionTime = timer.elapsed(); 735 status = 'done'; 736 }; 737 738 this.status = function() { 739 return status; 740 }; 741 742 var suites = {}; 743 744 this.suiteStarted = function(result) { 745 storeSuite(result); 746 }; 747 748 this.suiteDone = function(result) { 749 storeSuite(result); 750 }; 751 752 function storeSuite(result) { 753 suites[result.id] = result; 754 } 755 756 this.suites = function() { 757 return suites; 758 }; 759 760 var specs = []; 761 this.specStarted = function(result) { }; 762 763 this.specDone = function(result) { 764 specs.push(result); 765 }; 766 767 this.specResults = function(index, length) { 768 return specs.slice(index, index + length); 769 }; 770 771 this.specs = function() { 772 return specs; 773 }; 774 775 this.executionTime = function() { 776 return executionTime; 777 }; 778 779 } 780 781 return JsApiReporter; 782 }; 783 784 getJasmineRequireObj().Any = function() { 785 786 function Any(expectedObject) { 787 this.expectedObject = expectedObject; 788 } 789 790 Any.prototype.jasmineMatches = function(other) { 791 if (this.expectedObject == String) { 792 return typeof other == 'string' || other instanceof String; 793 } 794 795 if (this.expectedObject == Number) { 796 return typeof other == 'number' || other instanceof Number; 797 } 798 799 if (this.expectedObject == Function) { 800 return typeof other == 'function' || other instanceof Function; 801 } 802 803 if (this.expectedObject == Object) { 804 return typeof other == 'object'; 805 } 806 807 if (this.expectedObject == Boolean) { 808 return typeof other == 'boolean'; 809 } 810 811 return other instanceof this.expectedObject; 812 }; 813 814 Any.prototype.jasmineToString = function() { 815 return '<jasmine.any(' + this.expectedObject + ')>'; 816 }; 817 818 return Any; 819 }; 820 821 getJasmineRequireObj().CallTracker = function() { 822 823 function CallTracker() { 824 var calls = []; 825 826 this.track = function(context) { 827 calls.push(context); 828 }; 829 830 this.any = function() { 831 return !!calls.length; 832 }; 833 834 this.count = function() { 835 return calls.length; 836 }; 837 838 this.argsFor = function(index) { 839 var call = calls[index]; 840 return call ? call.args : []; 841 }; 842 843 this.all = function() { 844 return calls; 845 }; 846 847 this.allArgs = function() { 848 var callArgs = []; 849 for(var i = 0; i < calls.length; i++){ 850 callArgs.push(calls[i].args); 851 } 852 853 return callArgs; 854 }; 855 856 this.first = function() { 857 return calls[0]; 858 }; 859 860 this.mostRecent = function() { 861 return calls[calls.length - 1]; 862 }; 863 864 this.reset = function() { 865 calls = []; 866 }; 867 } 868 869 return CallTracker; 870 }; 871 872 getJasmineRequireObj().Clock = function() { 873 function Clock(global, delayedFunctionScheduler, mockDate) { 874 var self = this, 875 realTimingFunctions = { 876 setTimeout: global.setTimeout, 877 clearTimeout: global.clearTimeout, 878 setInterval: global.setInterval, 879 clearInterval: global.clearInterval 880 }, 881 fakeTimingFunctions = { 882 setTimeout: setTimeout, 883 clearTimeout: clearTimeout, 884 setInterval: setInterval, 885 clearInterval: clearInterval 886 }, 887 installed = false, 888 timer; 889 890 891 self.install = function() { 892 replace(global, fakeTimingFunctions); 893 timer = fakeTimingFunctions; 894 installed = true; 895 896 return self; 897 }; 898 899 self.uninstall = function() { 900 delayedFunctionScheduler.reset(); 901 mockDate.uninstall(); 902 replace(global, realTimingFunctions); 903 904 timer = realTimingFunctions; 905 installed = false; 906 }; 907 908 self.mockDate = function(initialDate) { 909 mockDate.install(initialDate); 910 }; 911 912 self.setTimeout = function(fn, delay, params) { 913 if (legacyIE()) { 914 if (arguments.length > 2) { 915 throw new Error('IE < 9 cannot support extra params to setTimeout without a polyfill'); 916 } 917 return timer.setTimeout(fn, delay); 918 } 919 return Function.prototype.apply.apply(timer.setTimeout, [global, arguments]); 920 }; 921 922 self.setInterval = function(fn, delay, params) { 923 if (legacyIE()) { 924 if (arguments.length > 2) { 925 throw new Error('IE < 9 cannot support extra params to setInterval without a polyfill'); 926 } 927 return timer.setInterval(fn, delay); 928 } 929 return Function.prototype.apply.apply(timer.setInterval, [global, arguments]); 930 }; 931 932 self.clearTimeout = function(id) { 933 return Function.prototype.call.apply(timer.clearTimeout, [global, id]); 934 }; 935 936 self.clearInterval = function(id) { 937 return Function.prototype.call.apply(timer.clearInterval, [global, id]); 938 }; 939 940 self.tick = function(millis) { 941 if (installed) { 942 mockDate.tick(millis); 943 delayedFunctionScheduler.tick(millis); 944 } else { 945 throw new Error('Mock clock is not installed, use jasmine.clock().install()'); 946 } 947 }; 948 949 return self; 950 951 function legacyIE() { 952 //if these methods are polyfilled, apply will be present 953 return !(realTimingFunctions.setTimeout || realTimingFunctions.setInterval).apply; 954 } 955 956 function replace(dest, source) { 957 for (var prop in source) { 958 dest[prop] = source[prop]; 959 } 960 } 961 962 function setTimeout(fn, delay) { 963 return delayedFunctionScheduler.scheduleFunction(fn, delay, argSlice(arguments, 2)); 964 } 965 966 function clearTimeout(id) { 967 return delayedFunctionScheduler.removeFunctionWithId(id); 968 } 969 970 function setInterval(fn, interval) { 971 return delayedFunctionScheduler.scheduleFunction(fn, interval, argSlice(arguments, 2), true); 972 } 973 974 function clearInterval(id) { 975 return delayedFunctionScheduler.removeFunctionWithId(id); 976 } 977 978 function argSlice(argsObj, n) { 979 return Array.prototype.slice.call(argsObj, n); 980 } 981 } 982 983 return Clock; 984 }; 985 986 getJasmineRequireObj().DelayedFunctionScheduler = function() { 987 function DelayedFunctionScheduler() { 988 var self = this; 989 var scheduledLookup = []; 990 var scheduledFunctions = {}; 991 var currentTime = 0; 992 var delayedFnCount = 0; 993 994 self.tick = function(millis) { 995 millis = millis || 0; 996 var endTime = currentTime + millis; 997 998 runScheduledFunctions(endTime); 999 currentTime = endTime; 1000 }; 1001 1002 self.scheduleFunction = function(funcToCall, millis, params, recurring, timeoutKey, runAtMillis) { 1003 var f; 1004 if (typeof(funcToCall) === 'string') { 1005 /* jshint evil: true */ 1006 f = function() { return eval(funcToCall); }; 1007 /* jshint evil: false */ 1008 } else { 1009 f = funcToCall; 1010 } 1011 1012 millis = millis || 0; 1013 timeoutKey = timeoutKey || ++delayedFnCount; 1014 runAtMillis = runAtMillis || (currentTime + millis); 1015 1016 var funcToSchedule = { 1017 runAtMillis: runAtMillis, 1018 funcToCall: f, 1019 recurring: recurring, 1020 params: params, 1021 timeoutKey: timeoutKey, 1022 millis: millis 1023 }; 1024 1025 if (runAtMillis in scheduledFunctions) { 1026 scheduledFunctions[runAtMillis].push(funcToSchedule); 1027 } else { 1028 scheduledFunctions[runAtMillis] = [funcToSchedule]; 1029 scheduledLookup.push(runAtMillis); 1030 scheduledLookup.sort(function (a, b) { 1031 return a - b; 1032 }); 1033 } 1034 1035 return timeoutKey; 1036 }; 1037 1038 self.removeFunctionWithId = function(timeoutKey) { 1039 for (var runAtMillis in scheduledFunctions) { 1040 var funcs = scheduledFunctions[runAtMillis]; 1041 var i = indexOfFirstToPass(funcs, function (func) { 1042 return func.timeoutKey === timeoutKey; 1043 }); 1044 1045 if (i > -1) { 1046 if (funcs.length === 1) { 1047 delete scheduledFunctions[runAtMillis]; 1048 deleteFromLookup(runAtMillis); 1049 } else { 1050 funcs.splice(i, 1); 1051 } 1052 1053 // intervals get rescheduled when executed, so there's never more 1054 // than a single scheduled function with a given timeoutKey 1055 break; 1056 } 1057 } 1058 }; 1059 1060 self.reset = function() { 1061 currentTime = 0; 1062 scheduledLookup = []; 1063 scheduledFunctions = {}; 1064 delayedFnCount = 0; 1065 }; 1066 1067 return self; 1068 1069 function indexOfFirstToPass(array, testFn) { 1070 var index = -1; 1071 1072 for (var i = 0; i < array.length; ++i) { 1073 if (testFn(array[i])) { 1074 index = i; 1075 break; 1076 } 1077 } 1078 1079 return index; 1080 } 1081 1082 function deleteFromLookup(key) { 1083 var value = Number(key); 1084 var i = indexOfFirstToPass(scheduledLookup, function (millis) { 1085 return millis === value; 1086 }); 1087 1088 if (i > -1) { 1089 scheduledLookup.splice(i, 1); 1090 } 1091 } 1092 1093 function reschedule(scheduledFn) { 1094 self.scheduleFunction(scheduledFn.funcToCall, 1095 scheduledFn.millis, 1096 scheduledFn.params, 1097 true, 1098 scheduledFn.timeoutKey, 1099 scheduledFn.runAtMillis + scheduledFn.millis); 1100 } 1101 1102 function runScheduledFunctions(endTime) { 1103 if (scheduledLookup.length === 0 || scheduledLookup[0] > endTime) { 1104 return; 1105 } 1106 1107 do { 1108 currentTime = scheduledLookup.shift(); 1109 1110 var funcsToRun = scheduledFunctions[currentTime]; 1111 delete scheduledFunctions[currentTime]; 1112 1113 for (var i = 0; i < funcsToRun.length; ++i) { 1114 var funcToRun = funcsToRun[i]; 1115 funcToRun.funcToCall.apply(null, funcToRun.params || []); 1116 1117 if (funcToRun.recurring) { 1118 reschedule(funcToRun); 1119 } 1120 } 1121 } while (scheduledLookup.length > 0 && 1122 // checking first if we're out of time prevents setTimeout(0) 1123 // scheduled in a funcToRun from forcing an extra iteration 1124 currentTime !== endTime && 1125 scheduledLookup[0] <= endTime); 1126 } 1127 } 1128 1129 return DelayedFunctionScheduler; 1130 }; 1131 1132 getJasmineRequireObj().ExceptionFormatter = function() { 1133 function ExceptionFormatter() { 1134 this.message = function(error) { 1135 var message = ''; 1136 1137 if (error.name && error.message) { 1138 message += error.name + ': ' + error.message; 1139 } else { 1140 message += error.toString() + ' thrown'; 1141 } 1142 1143 if (error.fileName || error.sourceURL) { 1144 message += ' in ' + (error.fileName || error.sourceURL); 1145 } 1146 1147 if (error.line || error.lineNumber) { 1148 message += ' (line ' + (error.line || error.lineNumber) + ')'; 1149 } 1150 1151 return message; 1152 }; 1153 1154 this.stack = function(error) { 1155 return error ? error.stack : null; 1156 }; 1157 } 1158 1159 return ExceptionFormatter; 1160 }; 1161 1162 getJasmineRequireObj().Expectation = function() { 1163 1164 var matchers = {}; 1165 1166 function Expectation(options) { 1167 this.util = options.util || { buildFailureMessage: function() {} }; 1168 this.customEqualityTesters = options.customEqualityTesters || []; 1169 this.actual = options.actual; 1170 this.addExpectationResult = options.addExpectationResult || function(){}; 1171 this.isNot = options.isNot; 1172 1173 for (var matcherName in matchers) { 1174 this[matcherName] = matchers[matcherName]; 1175 } 1176 } 1177 1178 Expectation.prototype.wrapCompare = function(name, matcherFactory) { 1179 return function() { 1180 var args = Array.prototype.slice.call(arguments, 0), 1181 expected = args.slice(0), 1182 message = ''; 1183 1184 args.unshift(this.actual); 1185 1186 var matcher = matcherFactory(this.util, this.customEqualityTesters), 1187 matcherCompare = matcher.compare; 1188 1189 function defaultNegativeCompare() { 1190 var result = matcher.compare.apply(null, args); 1191 result.pass = !result.pass; 1192 return result; 1193 } 1194 1195 if (this.isNot) { 1196 matcherCompare = matcher.negativeCompare || defaultNegativeCompare; 1197 } 1198 1199 var result = matcherCompare.apply(null, args); 1200 1201 if (!result.pass) { 1202 if (!result.message) { 1203 args.unshift(this.isNot); 1204 args.unshift(name); 1205 message = this.util.buildFailureMessage.apply(null, args); 1206 } else { 1207 if (Object.prototype.toString.apply(result.message) === '[object Function]') { 1208 message = result.message(); 1209 } else { 1210 message = result.message; 1211 } 1212 } 1213 } 1214 1215 if (expected.length == 1) { 1216 expected = expected[0]; 1217 } 1218 1219 // TODO: how many of these params are needed? 1220 this.addExpectationResult( 1221 result.pass, 1222 { 1223 matcherName: name, 1224 passed: result.pass, 1225 message: message, 1226 actual: this.actual, 1227 expected: expected // TODO: this may need to be arrayified/sliced 1228 } 1229 ); 1230 }; 1231 }; 1232 1233 Expectation.addCoreMatchers = function(matchers) { 1234 var prototype = Expectation.prototype; 1235 for (var matcherName in matchers) { 1236 var matcher = matchers[matcherName]; 1237 prototype[matcherName] = prototype.wrapCompare(matcherName, matcher); 1238 } 1239 }; 1240 1241 Expectation.addMatchers = function(matchersToAdd) { 1242 for (var name in matchersToAdd) { 1243 var matcher = matchersToAdd[name]; 1244 matchers[name] = Expectation.prototype.wrapCompare(name, matcher); 1245 } 1246 }; 1247 1248 Expectation.resetMatchers = function() { 1249 for (var name in matchers) { 1250 delete matchers[name]; 1251 } 1252 }; 1253 1254 Expectation.Factory = function(options) { 1255 options = options || {}; 1256 1257 var expect = new Expectation(options); 1258 1259 // TODO: this would be nice as its own Object - NegativeExpectation 1260 // TODO: copy instead of mutate options 1261 options.isNot = true; 1262 expect.not = new Expectation(options); 1263 1264 return expect; 1265 }; 1266 1267 return Expectation; 1268 }; 1269 1270 //TODO: expectation result may make more sense as a presentation of an expectation. 1271 getJasmineRequireObj().buildExpectationResult = function() { 1272 function buildExpectationResult(options) { 1273 var messageFormatter = options.messageFormatter || function() {}, 1274 stackFormatter = options.stackFormatter || function() {}; 1275 1276 return { 1277 matcherName: options.matcherName, 1278 expected: options.expected, 1279 actual: options.actual, 1280 message: message(), 1281 stack: stack(), 1282 passed: options.passed 1283 }; 1284 1285 function message() { 1286 if (options.passed) { 1287 return 'Passed.'; 1288 } else if (options.message) { 1289 return options.message; 1290 } else if (options.error) { 1291 return messageFormatter(options.error); 1292 } 1293 return ''; 1294 } 1295 1296 function stack() { 1297 if (options.passed) { 1298 return ''; 1299 } 1300 1301 var error = options.error; 1302 if (!error) { 1303 try { 1304 throw new Error(message()); 1305 } catch (e) { 1306 error = e; 1307 } 1308 } 1309 return stackFormatter(error); 1310 } 1311 } 1312 1313 return buildExpectationResult; 1314 }; 1315 1316 getJasmineRequireObj().MockDate = function() { 1317 function MockDate(global) { 1318 var self = this; 1319 var currentTime = 0; 1320 1321 if (!global || !global.Date) { 1322 self.install = function() {}; 1323 self.tick = function() {}; 1324 self.uninstall = function() {}; 1325 return self; 1326 } 1327 1328 var GlobalDate = global.Date; 1329 1330 self.install = function(mockDate) { 1331 if (mockDate instanceof GlobalDate) { 1332 currentTime = mockDate.getTime(); 1333 } else { 1334 currentTime = new GlobalDate().getTime(); 1335 } 1336 1337 global.Date = FakeDate; 1338 }; 1339 1340 self.tick = function(millis) { 1341 millis = millis || 0; 1342 currentTime = currentTime + millis; 1343 }; 1344 1345 self.uninstall = function() { 1346 currentTime = 0; 1347 global.Date = GlobalDate; 1348 }; 1349 1350 createDateProperties(); 1351 1352 return self; 1353 1354 function FakeDate() { 1355 if (arguments.length === 0) { 1356 return new GlobalDate(currentTime); 1357 } else { 1358 return new GlobalDate(arguments[0], arguments[1], arguments[2], 1359 arguments[3], arguments[4], arguments[5], arguments[6]); 1360 } 1361 } 1362 1363 function createDateProperties() { 1364 1365 FakeDate.now = function() { 1366 if (GlobalDate.now) { 1367 return currentTime; 1368 } else { 1369 throw new Error('Browser does not support Date.now()'); 1370 } 1371 }; 1372 1373 FakeDate.toSource = GlobalDate.toSource; 1374 FakeDate.toString = GlobalDate.toString; 1375 FakeDate.parse = GlobalDate.parse; 1376 FakeDate.UTC = GlobalDate.UTC; 1377 } 1378 } 1379 1380 return MockDate; 1381 }; 1382 1383 getJasmineRequireObj().ObjectContaining = function(j$) { 1384 1385 function ObjectContaining(sample) { 1386 this.sample = sample; 1387 } 1388 1389 ObjectContaining.prototype.jasmineMatches = function(other, mismatchKeys, mismatchValues) { 1390 if (typeof(this.sample) !== 'object') { throw new Error('You must provide an object to objectContaining, not \''+this.sample+'\'.'); } 1391 1392 mismatchKeys = mismatchKeys || []; 1393 mismatchValues = mismatchValues || []; 1394 1395 var hasKey = function(obj, keyName) { 1396 return obj !== null && !j$.util.isUndefined(obj[keyName]); 1397 }; 1398 1399 for (var property in this.sample) { 1400 if (!hasKey(other, property) && hasKey(this.sample, property)) { 1401 mismatchKeys.push('expected has key \'' + property + '\', but missing from actual.'); 1402 } 1403 else if (!j$.matchersUtil.equals(other[property], this.sample[property])) { 1404 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.'); 1405 } 1406 } 1407 1408 return (mismatchKeys.length === 0 && mismatchValues.length === 0); 1409 }; 1410 1411 ObjectContaining.prototype.jasmineToString = function() { 1412 return '<jasmine.objectContaining(' + j$.pp(this.sample) + ')>'; 1413 }; 1414 1415 return ObjectContaining; 1416 }; 1417 1418 getJasmineRequireObj().pp = function(j$) { 1419 1420 function PrettyPrinter() { 1421 this.ppNestLevel_ = 0; 1422 this.seen = []; 1423 } 1424 1425 PrettyPrinter.prototype.format = function(value) { 1426 this.ppNestLevel_++; 1427 try { 1428 if (j$.util.isUndefined(value)) { 1429 this.emitScalar('undefined'); 1430 } else if (value === null) { 1431 this.emitScalar('null'); 1432 } else if (value === 0 && 1/value === -Infinity) { 1433 this.emitScalar('-0'); 1434 } else if (value === j$.getGlobal()) { 1435 this.emitScalar('<global>'); 1436 } else if (value.jasmineToString) { 1437 this.emitScalar(value.jasmineToString()); 1438 } else if (typeof value === 'string') { 1439 this.emitString(value); 1440 } else if (j$.isSpy(value)) { 1441 this.emitScalar('spy on ' + value.and.identity()); 1442 } else if (value instanceof RegExp) { 1443 this.emitScalar(value.toString()); 1444 } else if (typeof value === 'function') { 1445 this.emitScalar('Function'); 1446 } else if (typeof value.nodeType === 'number') { 1447 this.emitScalar('HTMLNode'); 1448 } else if (value instanceof Date) { 1449 this.emitScalar('Date(' + value + ')'); 1450 } else if (j$.util.arrayContains(this.seen, value)) { 1451 this.emitScalar('<circular reference: ' + (j$.isArray_(value) ? 'Array' : 'Object') + '>'); 1452 } else if (j$.isArray_(value) || j$.isA_('Object', value)) { 1453 this.seen.push(value); 1454 if (j$.isArray_(value)) { 1455 this.emitArray(value); 1456 } else { 1457 this.emitObject(value); 1458 } 1459 this.seen.pop(); 1460 } else { 1461 this.emitScalar(value.toString()); 1462 } 1463 } finally { 1464 this.ppNestLevel_--; 1465 } 1466 }; 1467 1468 PrettyPrinter.prototype.iterateObject = function(obj, fn) { 1469 for (var property in obj) { 1470 if (!Object.prototype.hasOwnProperty.call(obj, property)) { continue; } 1471 fn(property, obj.__lookupGetter__ ? (!j$.util.isUndefined(obj.__lookupGetter__(property)) && 1472 obj.__lookupGetter__(property) !== null) : false); 1473 } 1474 }; 1475 1476 PrettyPrinter.prototype.emitArray = j$.unimplementedMethod_; 1477 PrettyPrinter.prototype.emitObject = j$.unimplementedMethod_; 1478 PrettyPrinter.prototype.emitScalar = j$.unimplementedMethod_; 1479 PrettyPrinter.prototype.emitString = j$.unimplementedMethod_; 1480 1481 function StringPrettyPrinter() { 1482 PrettyPrinter.call(this); 1483 1484 this.string = ''; 1485 } 1486 1487 j$.util.inherit(StringPrettyPrinter, PrettyPrinter); 1488 1489 StringPrettyPrinter.prototype.emitScalar = function(value) { 1490 this.append(value); 1491 }; 1492 1493 StringPrettyPrinter.prototype.emitString = function(value) { 1494 this.append('\'' + value + '\''); 1495 }; 1496 1497 StringPrettyPrinter.prototype.emitArray = function(array) { 1498 if (this.ppNestLevel_ > j$.MAX_PRETTY_PRINT_DEPTH) { 1499 this.append('Array'); 1500 return; 1501 } 1502 var length = Math.min(array.length, j$.MAX_PRETTY_PRINT_ARRAY_LENGTH); 1503 this.append('[ '); 1504 for (var i = 0; i < length; i++) { 1505 if (i > 0) { 1506 this.append(', '); 1507 } 1508 this.format(array[i]); 1509 } 1510 if(array.length > length){ 1511 this.append(', ...'); 1512 } 1513 this.append(' ]'); 1514 }; 1515 1516 StringPrettyPrinter.prototype.emitObject = function(obj) { 1517 if (this.ppNestLevel_ > j$.MAX_PRETTY_PRINT_DEPTH) { 1518 this.append('Object'); 1519 return; 1520 } 1521 1522 var self = this; 1523 this.append('{ '); 1524 var first = true; 1525 1526 this.iterateObject(obj, function(property, isGetter) { 1527 if (first) { 1528 first = false; 1529 } else { 1530 self.append(', '); 1531 } 1532 1533 self.append(property); 1534 self.append(': '); 1535 if (isGetter) { 1536 self.append('<getter>'); 1537 } else { 1538 self.format(obj[property]); 1539 } 1540 }); 1541 1542 this.append(' }'); 1543 }; 1544 1545 StringPrettyPrinter.prototype.append = function(value) { 1546 this.string += value; 1547 }; 1548 1549 return function(value) { 1550 var stringPrettyPrinter = new StringPrettyPrinter(); 1551 stringPrettyPrinter.format(value); 1552 return stringPrettyPrinter.string; 1553 }; 1554 }; 1555 1556 getJasmineRequireObj().QueueRunner = function(j$) { 1557 1558 function once(fn) { 1559 var called = false; 1560 return function() { 1561 if (!called) { 1562 called = true; 1563 fn(); 1564 } 1565 }; 1566 } 1567 1568 function QueueRunner(attrs) { 1569 this.fns = attrs.fns || []; 1570 this.onComplete = attrs.onComplete || function() {}; 1571 this.clearStack = attrs.clearStack || function(fn) {fn();}; 1572 this.onException = attrs.onException || function() {}; 1573 this.catchException = attrs.catchException || function() { return true; }; 1574 this.enforceTimeout = attrs.enforceTimeout || function() { return false; }; 1575 this.userContext = {}; 1576 this.timer = attrs.timeout || {setTimeout: setTimeout, clearTimeout: clearTimeout}; 1577 } 1578 1579 QueueRunner.prototype.execute = function() { 1580 this.run(this.fns, 0); 1581 }; 1582 1583 QueueRunner.prototype.run = function(fns, recursiveIndex) { 1584 var length = fns.length, 1585 self = this, 1586 iterativeIndex; 1587 1588 for(iterativeIndex = recursiveIndex; iterativeIndex < length; iterativeIndex++) { 1589 var fn = fns[iterativeIndex]; 1590 if (fn.length > 0) { 1591 return attemptAsync(fn); 1592 } else { 1593 attemptSync(fn); 1594 } 1595 } 1596 1597 var runnerDone = iterativeIndex >= length; 1598 1599 if (runnerDone) { 1600 this.clearStack(this.onComplete); 1601 } 1602 1603 function attemptSync(fn) { 1604 try { 1605 fn.call(self.userContext); 1606 } catch (e) { 1607 handleException(e); 1608 } 1609 } 1610 1611 function attemptAsync(fn) { 1612 var clearTimeout = function () { 1613 Function.prototype.apply.apply(self.timer.clearTimeout, [j$.getGlobal(), [timeoutId]]); 1614 }, 1615 next = once(function () { 1616 clearTimeout(timeoutId); 1617 self.run(fns, iterativeIndex + 1); 1618 }), 1619 timeoutId; 1620 1621 if (self.enforceTimeout()) { 1622 timeoutId = Function.prototype.apply.apply(self.timer.setTimeout, [j$.getGlobal(), [function() { 1623 self.onException(new Error('Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.')); 1624 next(); 1625 }, j$.DEFAULT_TIMEOUT_INTERVAL]]); 1626 } 1627 1628 try { 1629 fn.call(self.userContext, next); 1630 } catch (e) { 1631 handleException(e); 1632 next(); 1633 } 1634 } 1635 1636 function handleException(e) { 1637 self.onException(e); 1638 if (!self.catchException(e)) { 1639 //TODO: set a var when we catch an exception and 1640 //use a finally block to close the loop in a nice way.. 1641 throw e; 1642 } 1643 } 1644 }; 1645 1646 return QueueRunner; 1647 }; 1648 1649 getJasmineRequireObj().ReportDispatcher = function() { 1650 function ReportDispatcher(methods) { 1651 1652 var dispatchedMethods = methods || []; 1653 1654 for (var i = 0; i < dispatchedMethods.length; i++) { 1655 var method = dispatchedMethods[i]; 1656 this[method] = (function(m) { 1657 return function() { 1658 dispatch(m, arguments); 1659 }; 1660 }(method)); 1661 } 1662 1663 var reporters = []; 1664 1665 this.addReporter = function(reporter) { 1666 reporters.push(reporter); 1667 }; 1668 1669 return this; 1670 1671 function dispatch(method, args) { 1672 for (var i = 0; i < reporters.length; i++) { 1673 var reporter = reporters[i]; 1674 if (reporter[method]) { 1675 reporter[method].apply(reporter, args); 1676 } 1677 } 1678 } 1679 } 1680 1681 return ReportDispatcher; 1682 }; 1683 1684 1685 getJasmineRequireObj().SpyStrategy = function() { 1686 1687 function SpyStrategy(options) { 1688 options = options || {}; 1689 1690 var identity = options.name || 'unknown', 1691 originalFn = options.fn || function() {}, 1692 getSpy = options.getSpy || function() {}, 1693 plan = function() {}; 1694 1695 this.identity = function() { 1696 return identity; 1697 }; 1698 1699 this.exec = function() { 1700 return plan.apply(this, arguments); 1701 }; 1702 1703 this.callThrough = function() { 1704 plan = originalFn; 1705 return getSpy(); 1706 }; 1707 1708 this.returnValue = function(value) { 1709 plan = function() { 1710 return value; 1711 }; 1712 return getSpy(); 1713 }; 1714 1715 this.throwError = function(something) { 1716 var error = (something instanceof Error) ? something : new Error(something); 1717 plan = function() { 1718 throw error; 1719 }; 1720 return getSpy(); 1721 }; 1722 1723 this.callFake = function(fn) { 1724 plan = fn; 1725 return getSpy(); 1726 }; 1727 1728 this.stub = function(fn) { 1729 plan = function() {}; 1730 return getSpy(); 1731 }; 1732 } 1733 1734 return SpyStrategy; 1735 }; 1736 1737 getJasmineRequireObj().Suite = function() { 1738 function Suite(attrs) { 1739 this.env = attrs.env; 1740 this.id = attrs.id; 1741 this.parentSuite = attrs.parentSuite; 1742 this.description = attrs.description; 1743 this.onStart = attrs.onStart || function() {}; 1744 this.resultCallback = attrs.resultCallback || function() {}; 1745 this.clearStack = attrs.clearStack || function(fn) {fn();}; 1746 1747 this.beforeFns = []; 1748 this.afterFns = []; 1749 this.queueRunner = attrs.queueRunner || function() {}; 1750 this.disabled = false; 1751 1752 this.children = []; 1753 1754 this.result = { 1755 id: this.id, 1756 status: this.disabled ? 'disabled' : '', 1757 description: this.description, 1758 fullName: this.getFullName() 1759 }; 1760 } 1761 1762 Suite.prototype.getFullName = function() { 1763 var fullName = this.description; 1764 for (var parentSuite = this.parentSuite; parentSuite; parentSuite = parentSuite.parentSuite) { 1765 if (parentSuite.parentSuite) { 1766 fullName = parentSuite.description + ' ' + fullName; 1767 } 1768 } 1769 return fullName; 1770 }; 1771 1772 Suite.prototype.disable = function() { 1773 this.disabled = true; 1774 }; 1775 1776 Suite.prototype.beforeEach = function(fn) { 1777 this.beforeFns.unshift(fn); 1778 }; 1779 1780 Suite.prototype.afterEach = function(fn) { 1781 this.afterFns.unshift(fn); 1782 }; 1783 1784 Suite.prototype.addChild = function(child) { 1785 this.children.push(child); 1786 }; 1787 1788 Suite.prototype.execute = function(onComplete) { 1789 var self = this; 1790 if (this.disabled) { 1791 complete(); 1792 return; 1793 } 1794 1795 var allFns = []; 1796 1797 for (var i = 0; i < this.children.length; i++) { 1798 allFns.push(wrapChildAsAsync(this.children[i])); 1799 } 1800 1801 this.onStart(this); 1802 1803 this.queueRunner({ 1804 fns: allFns, 1805 onComplete: complete 1806 }); 1807 1808 function complete() { 1809 self.resultCallback(self.result); 1810 1811 if (onComplete) { 1812 onComplete(); 1813 } 1814 } 1815 1816 function wrapChildAsAsync(child) { 1817 return function(done) { child.execute(done); }; 1818 } 1819 }; 1820 1821 return Suite; 1822 }; 1823 1824 if (typeof window == void 0 && typeof exports == 'object') { 1825 exports.Suite = jasmineRequire.Suite; 1826 } 1827 1828 getJasmineRequireObj().Timer = function() { 1829 var defaultNow = (function(Date) { 1830 return function() { return new Date().getTime(); }; 1831 })(Date); 1832 1833 function Timer(options) { 1834 options = options || {}; 1835 1836 var now = options.now || defaultNow, 1837 startTime; 1838 1839 this.start = function() { 1840 startTime = now(); 1841 }; 1842 1843 this.elapsed = function() { 1844 return now() - startTime; 1845 }; 1846 } 1847 1848 return Timer; 1849 }; 1850 1851 getJasmineRequireObj().matchersUtil = function(j$) { 1852 // TODO: what to do about jasmine.pp not being inject? move to JSON.stringify? gut PrettyPrinter? 1853 1854 return { 1855 equals: function(a, b, customTesters) { 1856 customTesters = customTesters || []; 1857 1858 return eq(a, b, [], [], customTesters); 1859 }, 1860 1861 contains: function(haystack, needle, customTesters) { 1862 customTesters = customTesters || []; 1863 1864 if (Object.prototype.toString.apply(haystack) === '[object Array]') { 1865 for (var i = 0; i < haystack.length; i++) { 1866 if (eq(haystack[i], needle, [], [], customTesters)) { 1867 return true; 1868 } 1869 } 1870 return false; 1871 } 1872 return !!haystack && haystack.indexOf(needle) >= 0; 1873 }, 1874 1875 buildFailureMessage: function() { 1876 var args = Array.prototype.slice.call(arguments, 0), 1877 matcherName = args[0], 1878 isNot = args[1], 1879 actual = args[2], 1880 expected = args.slice(3), 1881 englishyPredicate = matcherName.replace(/[A-Z]/g, function(s) { return ' ' + s.toLowerCase(); }); 1882 1883 var message = 'Expected ' + 1884 j$.pp(actual) + 1885 (isNot ? ' not ' : ' ') + 1886 englishyPredicate; 1887 1888 if (expected.length > 0) { 1889 for (var i = 0; i < expected.length; i++) { 1890 if (i > 0) { 1891 message += ','; 1892 } 1893 message += ' ' + j$.pp(expected[i]); 1894 } 1895 } 1896 1897 return message + '.'; 1898 } 1899 }; 1900 1901 // Equality function lovingly adapted from isEqual in 1902 // [Underscore](http://underscorejs.org) 1903 function eq(a, b, aStack, bStack, customTesters) { 1904 var result = true; 1905 1906 for (var i = 0; i < customTesters.length; i++) { 1907 var customTesterResult = customTesters[i](a, b); 1908 if (!j$.util.isUndefined(customTesterResult)) { 1909 return customTesterResult; 1910 } 1911 } 1912 1913 if (a instanceof j$.Any) { 1914 result = a.jasmineMatches(b); 1915 if (result) { 1916 return true; 1917 } 1918 } 1919 1920 if (b instanceof j$.Any) { 1921 result = b.jasmineMatches(a); 1922 if (result) { 1923 return true; 1924 } 1925 } 1926 1927 if (b instanceof j$.ObjectContaining) { 1928 result = b.jasmineMatches(a); 1929 if (result) { 1930 return true; 1931 } 1932 } 1933 1934 if (a instanceof Error && b instanceof Error) { 1935 return a.message == b.message; 1936 } 1937 1938 // Identical objects are equal. `0 === -0`, but they aren't identical. 1939 // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal). 1940 if (a === b) { return a !== 0 || 1 / a == 1 / b; } 1941 // A strict comparison is necessary because `null == undefined`. 1942 if (a === null || b === null) { return a === b; } 1943 var className = Object.prototype.toString.call(a); 1944 if (className != Object.prototype.toString.call(b)) { return false; } 1945 switch (className) { 1946 // Strings, numbers, dates, and booleans are compared by value. 1947 case '[object String]': 1948 // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is 1949 // equivalent to `new String("5")`. 1950 return a == String(b); 1951 case '[object Number]': 1952 // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for 1953 // other numeric values. 1954 return a != +a ? b != +b : (a === 0 ? 1 / a == 1 / b : a == +b); 1955 case '[object Date]': 1956 case '[object Boolean]': 1957 // Coerce dates and booleans to numeric primitive values. Dates are compared by their 1958 // millisecond representations. Note that invalid dates with millisecond representations 1959 // of `NaN` are not equivalent. 1960 return +a == +b; 1961 // RegExps are compared by their source patterns and flags. 1962 case '[object RegExp]': 1963 return a.source == b.source && 1964 a.global == b.global && 1965 a.multiline == b.multiline && 1966 a.ignoreCase == b.ignoreCase; 1967 } 1968 if (typeof a != 'object' || typeof b != 'object') { return false; } 1969 // Assume equality for cyclic structures. The algorithm for detecting cyclic 1970 // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`. 1971 var length = aStack.length; 1972 while (length--) { 1973 // Linear search. Performance is inversely proportional to the number of 1974 // unique nested structures. 1975 if (aStack[length] == a) { return bStack[length] == b; } 1976 } 1977 // Add the first object to the stack of traversed objects. 1978 aStack.push(a); 1979 bStack.push(b); 1980 var size = 0; 1981 // Recursively compare objects and arrays. 1982 if (className == '[object Array]') { 1983 // Compare array lengths to determine if a deep comparison is necessary. 1984 size = a.length; 1985 result = size == b.length; 1986 if (result) { 1987 // Deep compare the contents, ignoring non-numeric properties. 1988 while (size--) { 1989 if (!(result = eq(a[size], b[size], aStack, bStack, customTesters))) { break; } 1990 } 1991 } 1992 } else { 1993 // Objects with different constructors are not equivalent, but `Object`s 1994 // from different frames are. 1995 var aCtor = a.constructor, bCtor = b.constructor; 1996 if (aCtor !== bCtor && !(isFunction(aCtor) && (aCtor instanceof aCtor) && 1997 isFunction(bCtor) && (bCtor instanceof bCtor))) { 1998 return false; 1999 } 2000 // Deep compare objects. 2001 for (var key in a) { 2002 if (has(a, key)) { 2003 // Count the expected number of properties. 2004 size++; 2005 // Deep compare each member. 2006 if (!(result = has(b, key) && eq(a[key], b[key], aStack, bStack, customTesters))) { break; } 2007 } 2008 } 2009 // Ensure that both objects contain the same number of properties. 2010 if (result) { 2011 for (key in b) { 2012 if (has(b, key) && !(size--)) { break; } 2013 } 2014 result = !size; 2015 } 2016 } 2017 // Remove the first object from the stack of traversed objects. 2018 aStack.pop(); 2019 bStack.pop(); 2020 2021 return result; 2022 2023 function has(obj, key) { 2024 return obj.hasOwnProperty(key); 2025 } 2026 2027 function isFunction(obj) { 2028 return typeof obj === 'function'; 2029 } 2030 } 2031 }; 2032 2033 getJasmineRequireObj().toBe = function() { 2034 function toBe() { 2035 return { 2036 compare: function(actual, expected) { 2037 return { 2038 pass: actual === expected 2039 }; 2040 } 2041 }; 2042 } 2043 2044 return toBe; 2045 }; 2046 2047 getJasmineRequireObj().toBeCloseTo = function() { 2048 2049 function toBeCloseTo() { 2050 return { 2051 compare: function(actual, expected, precision) { 2052 if (precision !== 0) { 2053 precision = precision || 2; 2054 } 2055 2056 return { 2057 pass: Math.abs(expected - actual) < (Math.pow(10, -precision) / 2) 2058 }; 2059 } 2060 }; 2061 } 2062 2063 return toBeCloseTo; 2064 }; 2065 2066 getJasmineRequireObj().toBeDefined = function() { 2067 function toBeDefined() { 2068 return { 2069 compare: function(actual) { 2070 return { 2071 pass: (void 0 !== actual) 2072 }; 2073 } 2074 }; 2075 } 2076 2077 return toBeDefined; 2078 }; 2079 2080 getJasmineRequireObj().toBeFalsy = function() { 2081 function toBeFalsy() { 2082 return { 2083 compare: function(actual) { 2084 return { 2085 pass: !!!actual 2086 }; 2087 } 2088 }; 2089 } 2090 2091 return toBeFalsy; 2092 }; 2093 2094 getJasmineRequireObj().toBeGreaterThan = function() { 2095 2096 function toBeGreaterThan() { 2097 return { 2098 compare: function(actual, expected) { 2099 return { 2100 pass: actual > expected 2101 }; 2102 } 2103 }; 2104 } 2105 2106 return toBeGreaterThan; 2107 }; 2108 2109 2110 getJasmineRequireObj().toBeLessThan = function() { 2111 function toBeLessThan() { 2112 return { 2113 2114 compare: function(actual, expected) { 2115 return { 2116 pass: actual < expected 2117 }; 2118 } 2119 }; 2120 } 2121 2122 return toBeLessThan; 2123 }; 2124 getJasmineRequireObj().toBeNaN = function(j$) { 2125 2126 function toBeNaN() { 2127 return { 2128 compare: function(actual) { 2129 var result = { 2130 pass: (actual !== actual) 2131 }; 2132 2133 if (result.pass) { 2134 result.message = 'Expected actual not to be NaN.'; 2135 } else { 2136 result.message = function() { return 'Expected ' + j$.pp(actual) + ' to be NaN.'; }; 2137 } 2138 2139 return result; 2140 } 2141 }; 2142 } 2143 2144 return toBeNaN; 2145 }; 2146 2147 getJasmineRequireObj().toBeNull = function() { 2148 2149 function toBeNull() { 2150 return { 2151 compare: function(actual) { 2152 return { 2153 pass: actual === null 2154 }; 2155 } 2156 }; 2157 } 2158 2159 return toBeNull; 2160 }; 2161 2162 getJasmineRequireObj().toBeTruthy = function() { 2163 2164 function toBeTruthy() { 2165 return { 2166 compare: function(actual) { 2167 return { 2168 pass: !!actual 2169 }; 2170 } 2171 }; 2172 } 2173 2174 return toBeTruthy; 2175 }; 2176 2177 getJasmineRequireObj().toBeUndefined = function() { 2178 2179 function toBeUndefined() { 2180 return { 2181 compare: function(actual) { 2182 return { 2183 pass: void 0 === actual 2184 }; 2185 } 2186 }; 2187 } 2188 2189 return toBeUndefined; 2190 }; 2191 2192 getJasmineRequireObj().toContain = function() { 2193 function toContain(util, customEqualityTesters) { 2194 customEqualityTesters = customEqualityTesters || []; 2195 2196 return { 2197 compare: function(actual, expected) { 2198 2199 return { 2200 pass: util.contains(actual, expected, customEqualityTesters) 2201 }; 2202 } 2203 }; 2204 } 2205 2206 return toContain; 2207 }; 2208 2209 getJasmineRequireObj().toEqual = function() { 2210 2211 function toEqual(util, customEqualityTesters) { 2212 customEqualityTesters = customEqualityTesters || []; 2213 2214 return { 2215 compare: function(actual, expected) { 2216 var result = { 2217 pass: false 2218 }; 2219 2220 result.pass = util.equals(actual, expected, customEqualityTesters); 2221 2222 return result; 2223 } 2224 }; 2225 } 2226 2227 return toEqual; 2228 }; 2229 2230 getJasmineRequireObj().toHaveBeenCalled = function(j$) { 2231 2232 function toHaveBeenCalled() { 2233 return { 2234 compare: function(actual) { 2235 var result = {}; 2236 2237 if (!j$.isSpy(actual)) { 2238 throw new Error('Expected a spy, but got ' + j$.pp(actual) + '.'); 2239 } 2240 2241 if (arguments.length > 1) { 2242 throw new Error('toHaveBeenCalled does not take arguments, use toHaveBeenCalledWith'); 2243 } 2244 2245 result.pass = actual.calls.any(); 2246 2247 result.message = result.pass ? 2248 'Expected spy ' + actual.and.identity() + ' not to have been called.' : 2249 'Expected spy ' + actual.and.identity() + ' to have been called.'; 2250 2251 return result; 2252 } 2253 }; 2254 } 2255 2256 return toHaveBeenCalled; 2257 }; 2258 2259 getJasmineRequireObj().toHaveBeenCalledWith = function(j$) { 2260 2261 function toHaveBeenCalledWith(util, customEqualityTesters) { 2262 return { 2263 compare: function() { 2264 var args = Array.prototype.slice.call(arguments, 0), 2265 actual = args[0], 2266 expectedArgs = args.slice(1), 2267 result = { pass: false }; 2268 2269 if (!j$.isSpy(actual)) { 2270 throw new Error('Expected a spy, but got ' + j$.pp(actual) + '.'); 2271 } 2272 2273 if (!actual.calls.any()) { 2274 result.message = function() { return 'Expected spy ' + actual.and.identity() + ' to have been called with ' + j$.pp(expectedArgs) + ' but it was never called.'; }; 2275 return result; 2276 } 2277 2278 if (util.contains(actual.calls.allArgs(), expectedArgs, customEqualityTesters)) { 2279 result.pass = true; 2280 result.message = function() { return 'Expected spy ' + actual.and.identity() + ' not to have been called with ' + j$.pp(expectedArgs) + ' but it was.'; }; 2281 } else { 2282 result.message = function() { return 'Expected spy ' + actual.and.identity() + ' to have been called with ' + j$.pp(expectedArgs) + ' but actual calls were ' + j$.pp(actual.calls.allArgs()).replace(/^\[ | \]$/g, '') + '.'; }; 2283 } 2284 2285 return result; 2286 } 2287 }; 2288 } 2289 2290 return toHaveBeenCalledWith; 2291 }; 2292 2293 getJasmineRequireObj().toMatch = function() { 2294 2295 function toMatch() { 2296 return { 2297 compare: function(actual, expected) { 2298 var regexp = new RegExp(expected); 2299 2300 return { 2301 pass: regexp.test(actual) 2302 }; 2303 } 2304 }; 2305 } 2306 2307 return toMatch; 2308 }; 2309 2310 getJasmineRequireObj().toThrow = function(j$) { 2311 2312 function toThrow(util) { 2313 return { 2314 compare: function(actual, expected) { 2315 var result = { pass: false }, 2316 threw = false, 2317 thrown; 2318 2319 if (typeof actual != 'function') { 2320 throw new Error('Actual is not a Function'); 2321 } 2322 2323 try { 2324 actual(); 2325 } catch (e) { 2326 threw = true; 2327 thrown = e; 2328 } 2329 2330 if (!threw) { 2331 result.message = 'Expected function to throw an exception.'; 2332 return result; 2333 } 2334 2335 if (arguments.length == 1) { 2336 result.pass = true; 2337 result.message = function() { return 'Expected function not to throw, but it threw ' + j$.pp(thrown) + '.'; }; 2338 2339 return result; 2340 } 2341 2342 if (util.equals(thrown, expected)) { 2343 result.pass = true; 2344 result.message = function() { return 'Expected function not to throw ' + j$.pp(expected) + '.'; }; 2345 } else { 2346 result.message = function() { return 'Expected function to throw ' + j$.pp(expected) + ', but it threw ' + j$.pp(thrown) + '.'; }; 2347 } 2348 2349 return result; 2350 } 2351 }; 2352 } 2353 2354 return toThrow; 2355 }; 2356 2357 getJasmineRequireObj().toThrowError = function(j$) { 2358 function toThrowError (util) { 2359 return { 2360 compare: function(actual) { 2361 var threw = false, 2362 pass = {pass: true}, 2363 fail = {pass: false}, 2364 thrown, 2365 errorType, 2366 message, 2367 regexp, 2368 name, 2369 constructorName; 2370 2371 if (typeof actual != 'function') { 2372 throw new Error('Actual is not a Function'); 2373 } 2374 2375 extractExpectedParams.apply(null, arguments); 2376 2377 try { 2378 actual(); 2379 } catch (e) { 2380 threw = true; 2381 thrown = e; 2382 } 2383 2384 if (!threw) { 2385 fail.message = 'Expected function to throw an Error.'; 2386 return fail; 2387 } 2388 2389 if (!(thrown instanceof Error)) { 2390 fail.message = function() { return 'Expected function to throw an Error, but it threw ' + j$.pp(thrown) + '.'; }; 2391 return fail; 2392 } 2393 2394 if (arguments.length == 1) { 2395 pass.message = 'Expected function not to throw an Error, but it threw ' + fnNameFor(thrown) + '.'; 2396 return pass; 2397 } 2398 2399 if (errorType) { 2400 name = fnNameFor(errorType); 2401 constructorName = fnNameFor(thrown.constructor); 2402 } 2403 2404 if (errorType && message) { 2405 if (thrown.constructor == errorType && util.equals(thrown.message, message)) { 2406 pass.message = function() { return 'Expected function not to throw ' + name + ' with message ' + j$.pp(message) + '.'; }; 2407 return pass; 2408 } else { 2409 fail.message = function() { return 'Expected function to throw ' + name + ' with message ' + j$.pp(message) + 2410 ', but it threw ' + constructorName + ' with message ' + j$.pp(thrown.message) + '.'; }; 2411 return fail; 2412 } 2413 } 2414 2415 if (errorType && regexp) { 2416 if (thrown.constructor == errorType && regexp.test(thrown.message)) { 2417 pass.message = function() { return 'Expected function not to throw ' + name + ' with message matching ' + j$.pp(regexp) + '.'; }; 2418 return pass; 2419 } else { 2420 fail.message = function() { return 'Expected function to throw ' + name + ' with message matching ' + j$.pp(regexp) + 2421 ', but it threw ' + constructorName + ' with message ' + j$.pp(thrown.message) + '.'; }; 2422 return fail; 2423 } 2424 } 2425 2426 if (errorType) { 2427 if (thrown.constructor == errorType) { 2428 pass.message = 'Expected function not to throw ' + name + '.'; 2429 return pass; 2430 } else { 2431 fail.message = 'Expected function to throw ' + name + ', but it threw ' + constructorName + '.'; 2432 return fail; 2433 } 2434 } 2435 2436 if (message) { 2437 if (thrown.message == message) { 2438 pass.message = function() { return 'Expected function not to throw an exception with message ' + j$.pp(message) + '.'; }; 2439 return pass; 2440 } else { 2441 fail.message = function() { return 'Expected function to throw an exception with message ' + j$.pp(message) + 2442 ', but it threw an exception with message ' + j$.pp(thrown.message) + '.'; }; 2443 return fail; 2444 } 2445 } 2446 2447 if (regexp) { 2448 if (regexp.test(thrown.message)) { 2449 pass.message = function() { return 'Expected function not to throw an exception with a message matching ' + j$.pp(regexp) + '.'; }; 2450 return pass; 2451 } else { 2452 fail.message = function() { return 'Expected function to throw an exception with a message matching ' + j$.pp(regexp) + 2453 ', but it threw an exception with message ' + j$.pp(thrown.message) + '.'; }; 2454 return fail; 2455 } 2456 } 2457 2458 function fnNameFor(func) { 2459 return func.name || func.toString().match(/^\s*function\s*(\w*)\s*\(/)[1]; 2460 } 2461 2462 function extractExpectedParams() { 2463 if (arguments.length == 1) { 2464 return; 2465 } 2466 2467 if (arguments.length == 2) { 2468 var expected = arguments[1]; 2469 2470 if (expected instanceof RegExp) { 2471 regexp = expected; 2472 } else if (typeof expected == 'string') { 2473 message = expected; 2474 } else if (checkForAnErrorType(expected)) { 2475 errorType = expected; 2476 } 2477 2478 if (!(errorType || message || regexp)) { 2479 throw new Error('Expected is not an Error, string, or RegExp.'); 2480 } 2481 } else { 2482 if (checkForAnErrorType(arguments[1])) { 2483 errorType = arguments[1]; 2484 } else { 2485 throw new Error('Expected error type is not an Error.'); 2486 } 2487 2488 if (arguments[2] instanceof RegExp) { 2489 regexp = arguments[2]; 2490 } else if (typeof arguments[2] == 'string') { 2491 message = arguments[2]; 2492 } else { 2493 throw new Error('Expected error message is not a string or RegExp.'); 2494 } 2495 } 2496 } 2497 2498 function checkForAnErrorType(type) { 2499 if (typeof type !== 'function') { 2500 return false; 2501 } 2502 2503 var Surrogate = function() {}; 2504 Surrogate.prototype = type.prototype; 2505 return (new Surrogate()) instanceof Error; 2506 } 2507 } 2508 }; 2509 } 2510 2511 return toThrowError; 2512 }; 2513 2514 getJasmineRequireObj().version = function() { 2515 return '2.0.1'; 2516 };