From 843bd355d25ebf2369aec79f98cb6704d38497e9 Mon Sep 17 00:00:00 2001 From: Misko Hevery Date: Fri, 9 Apr 2010 16:20:15 -0700 Subject: various bug fixes --- angular-debug.js | 86 +- example/temp.html | 9 + jsTestDriver.conf | 4 +- lib/jasmine-jstd-adapter/JasmineAdapter.js | 181 +-- lib/jasmine/jasmine-0.10.1.js | 2276 --------------------------- lib/jasmine/jasmine-0.10.3.js | 2331 ++++++++++++++++++++++++++++ lib/jstestdriver/JsTestDriver.jar | Bin 3133666 -> 3133701 bytes src/Angular.js | 2 +- src/Compiler.js | 14 +- src/Scope.js | 5 +- src/angular-bootstrap.js | 2 +- src/apis.js | 4 +- src/services.js | 26 +- src/widgets.js | 35 +- test/ApiTest.js | 4 + test/ValidatorsTest.js | 2 +- test/markupSpec.js | 5 + test/servicesSpec.js | 14 + test/widgetsSpec.js | 9 +- 19 files changed, 2574 insertions(+), 2435 deletions(-) create mode 100644 example/temp.html delete mode 100644 lib/jasmine/jasmine-0.10.1.js create mode 100644 lib/jasmine/jasmine-0.10.3.js diff --git a/angular-debug.js b/angular-debug.js index c3f419f7..dd74428a 100644 --- a/angular-debug.js +++ b/angular-debug.js @@ -343,7 +343,7 @@ function merge(src, dst) { } function compile(element, parentScope, overrides) { - var compiler = new Compiler(angularTextMarkup, angularAttrMarkup, angularDirective, angularWidget); + var compiler = new Compiler(angularTextMarkup, angularAttrMarkup, angularDirective, angularWidget), $element = jqLite(element), parent = extend({}, parentScope); parent.$element = $element; @@ -641,8 +641,8 @@ Compiler.prototype = { }; function eachTextNode(element, fn){ - var i, chldNodes = element[0].childNodes || [], size = chldNodes.length, chld; - for (i = 0; i < size; i++) { + var i, chldNodes = element[0].childNodes || [], chld; + for (i = 0; i < chldNodes.length; i++) { if(isTextNode(chld = chldNodes[i])) { fn(jqLite(chld), i); } @@ -650,8 +650,8 @@ function eachTextNode(element, fn){ } function eachNode(element, fn){ - var i, chldNodes = element[0].childNodes || [], size = chldNodes.length, chld; - for (i = 0; i < size; i++) { + var i, chldNodes = element[0].childNodes || [], chld; + for (i = 0; i < chldNodes.length; i++) { if(!isTextNode(chld = chldNodes[i])) { fn(jqLite(chld), i); } @@ -659,12 +659,12 @@ function eachNode(element, fn){ } function eachAttribute(element, fn){ - var i, attrs = element[0].attributes || [], size = attrs.length, chld, attr, attrValue = {}; - for (i = 0; i < size; i++) { + var i, attrs = element[0].attributes || [], chld, attr, attrValue = {}; + for (i = 0; i < attrs.length; i++) { attr = attrs[i]; attrValue[attr.name] = attr.value; } - foreach(attrValue, fn); + foreachSorted(attrValue, fn); } function getter(instance, path, unboundFn) { @@ -848,7 +848,10 @@ function createScope(parent, services, existing) { } foreach(services, function(_, name){ - instance[name] = inject(name); + var service = inject(name); + if (service) { + instance[name] = service; + } }); return instance; @@ -2026,7 +2029,9 @@ var angularGlobal = { var angularCollection = { 'size': size }; -var angularObject = {}; +var angularObject = { + 'extend': extend +}; var angularArray = { 'indexOf': indexOf, 'include': includes, @@ -3135,9 +3140,11 @@ function valueAccessor(scope, element) { required = required || required === ''; if (!validator) throw "Validator named '" + validatorName + "' not found."; function validate(value) { - var error = required && !trim(value) ? - "Required" : - validator({state:scope, scope:{get:scope.$get, set:scope.$set}}, value); + var error, + validateScope = extend(new (extend(function(){}, {prototype:scope}))(), {$element:element}); + error = required && !trim(value) ? + "Required" : + validator({state:validateScope, scope:{get:validateScope.$get, set:validateScope.$set}}, value); if (error !== lastError) { elementError(element, NG_VALIDATION_ERROR, error); lastError = error; @@ -3298,7 +3305,8 @@ angularWidget('NG:INCLUDE', function(element){ angularWidget('NG:SWITCH', function ngSwitch(element){ var compiler = this, watchExpr = element.attr("on"), - whenFn = ngSwitch[element.attr("using") || 'equals']; + whenExpr = (element.attr("using") || 'equals').split(":"); + whenFn = ngSwitch[whenExpr.shift()]; changeExpr = element.attr('change') || '', cases = []; if (!whenFn) throw "Using expression '" + usingExpr + "' unknown."; @@ -3307,7 +3315,11 @@ angularWidget('NG:SWITCH', function ngSwitch(element){ if (when) { cases.push({ when: function(scope, value){ - return whenFn.call(scope, value, when); + var args = [value, when]; + foreach(whenExpr, function(arg){ + args.push(arg); + }); + return whenFn.apply(scope, args); }, change: changeExpr, element: caseElement, @@ -3320,13 +3332,10 @@ angularWidget('NG:SWITCH', function ngSwitch(element){ var scope = this, childScope; this.$watch(watchExpr, function(value){ element.html(''); - childScope = null; - var params = {}; + childScope = createScope(scope); foreach(cases, function(switchCase){ - if (switchCase.when(params, value)) { + if (switchCase.when(childScope, value)) { element.append(switchCase.element); - childScope = createScope(scope); - extend(childScope, params); childScope.$tryEval(switchCase.change, element); switchCase.template(switchCase.element, childScope); childScope.$init(); @@ -3341,13 +3350,15 @@ angularWidget('NG:SWITCH', function ngSwitch(element){ equals: function(on, when) { return on == when; }, - route: function(on, when) { - var regex = '^' + when.replace(/[\.\\\(\)\^\$]/g, "\$1") + '$', params = [], self = this; + route: function(on, when, dstName) { + var regex = '^' + when.replace(/[\.\\\(\)\^\$]/g, "\$1") + '$', + params = [], + dst = {}; foreach(when.split(/\W/), function(param){ if (param) { var paramRegExp = new RegExp(":" + param + "([\\W])"); if (regex.match(paramRegExp)) { - regex = regex.replace(paramRegExp, "(.*)$1"); + regex = regex.replace(paramRegExp, "([^\/]*)$1"); params.push(param); } } @@ -3355,8 +3366,9 @@ angularWidget('NG:SWITCH', function ngSwitch(element){ var match = on.match(new RegExp(regex)); if (match) { foreach(params, function(name, index){ - self[name] = match[index + 1]; + dst[name] = match[index + 1]; }); + if (dstName) this.$set(dstName, dst); } return match; } @@ -3370,6 +3382,7 @@ var URL_MATCH = /^(file|ftp|http|https):\/\/(\w+:{0,1}\w*@)?([\w\.]*)(:([0-9]+)) var DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp':21}; angularService("$location", function(browser){ var scope = this, location = {parse:parse, toString:toString}; + var lastHash; function parse(url){ if (isDefined(url)) { var match = URL_MATCH.exec(url); @@ -3381,16 +3394,25 @@ angularService("$location", function(browser){ location.path = match[6]; location.search = parseKeyValue(match[8]); location.hash = match[9]; - if (location.hash) location.hash = location.hash.substr(1); + if (location.hash) + location.hash = location.hash.substr(1); + lastHash = location.hash; location.hashPath = match[11] || ''; location.hashSearch = parseKeyValue(match[13]); } } } function toString() { - var hashKeyValue = toKeyValue(location.hashSearch), - hash = (location.hashPath ? location.hashPath : '') + (hashKeyValue ? '?' + hashKeyValue : ''); - return location.href.split('#')[0] + '#' + (hash ? hash : ''); + if (lastHash === location.hash) { + var hashKeyValue = toKeyValue(location.hashSearch), + hash = (location.hashPath ? location.hashPath : '') + (hashKeyValue ? '?' + hashKeyValue : ''), + url = location.href.split('#')[0] + '#' + (hash ? hash : ''); + if (url !== location.href) parse(url); + return url; + } else { + parse(location.href.split('#')[0] + '#' + location.hash); + return toString(); + } } browser.watchUrl(function(url){ parse(url); @@ -3398,11 +3420,7 @@ angularService("$location", function(browser){ }); parse(browser.getUrl()); this.$onEval(PRIORITY_LAST, function(){ - var href = toString(); - if (href != location.href) { - browser.setUrl(href); - location.href = href; - } + browser.setUrl(toString()); }); return location; }, {inject: ['$browser']}); @@ -3432,6 +3450,7 @@ angularService("$hover", function(browser) { tooltip.arrow.addClass('ng-arrow-right'); tooltip.arrow.css({left: (width + 1)+'px'}); tooltip.callout.css({ + position: 'fixed', left: (elementRect.left - arrowWidth - width - 4) + "px", top: (elementRect.top - 3) + "px", width: width + "px" @@ -3439,6 +3458,7 @@ angularService("$hover", function(browser) { } else { tooltip.arrow.addClass('ng-arrow-left'); tooltip.callout.css({ + position: 'fixed', left: (elementRect.right + arrowWidth) + "px", top: (elementRect.top - 3) + "px", width: width + "px" diff --git a/example/temp.html b/example/temp.html new file mode 100644 index 00000000..3580249d --- /dev/null +++ b/example/temp.html @@ -0,0 +1,9 @@ + + + + + + + {{'first'}}
{{'second'}}
+ + diff --git a/jsTestDriver.conf b/jsTestDriver.conf index a0cae9a4..9c2ef63f 100644 --- a/jsTestDriver.conf +++ b/jsTestDriver.conf @@ -1,9 +1,9 @@ server: http://localhost:9876 load: - - lib/jasmine/jasmine-0.10.1.js + - lib/jasmine/jasmine-0.10.3.js - lib/jasmine-jstd-adapter/JasmineAdapter.js - - lib/webtoolkit/webtoolkit.base64.js +# - lib/webtoolkit/webtoolkit.base64.js # - lib/jquery/jquery-1.4.2.js # - lib/underscore/underscore.js - src/Angular.js diff --git a/lib/jasmine-jstd-adapter/JasmineAdapter.js b/lib/jasmine-jstd-adapter/JasmineAdapter.js index 83a1deed..ba54251a 100644 --- a/lib/jasmine-jstd-adapter/JasmineAdapter.js +++ b/lib/jasmine-jstd-adapter/JasmineAdapter.js @@ -1,96 +1,103 @@ /** * @fileoverview Jasmine JsTestDriver Adapter. * @author ibolmo@gmail.com (Olmo Maldonado) + * @author misko@hevery.com (Misko Hevery) */ (function() { -// Suite/TestCase before and after function stacks. -var before = []; -var after = []; - -jasmine.Env.prototype.describe = (function(describe){ - - // TODO(ibolmo): Support nested describes. - return function(description, specDefinitions){ - this.currentTestCase = TestCase(description); - return describe.call(this, description, specDefinitions); - }; - -})(jasmine.Env.prototype.describe); - - -jasmine.Env.prototype.it = (function(it){ - - return function(desc, func){ - var spec = it.call(this, desc, func); - this.currentTestCase.prototype['test that it ' + desc] = func; - return spec; - }; - -})(jasmine.Env.prototype.it); - - -jasmine.Env.prototype.beforeEach = (function(beforeEach){ - - // TODO(ibolmo): Support beforeEach TestCase. - return function(beforeEachFunction) { - beforeEach.call(this, beforeEachFunction); - if (this.currentTestCase) { - this.currentTestCase.prototype.setUp = beforeEachFunction; - } else { - before.push(beforeEachFunction); - } - }; - -})(jasmine.Env.prototype.beforeEach); - - -jasmine.Env.prototype.afterEach = (function(afterEach){ - - // TODO(ibolmo): Support afterEach TestCase. - return function(afterEachFunction) { - afterEach.call(this, afterEachFunction); - if (this.currentTestCase) { - this.currentTestCase.prototype.tearDown = afterEachFunction; - } else { - after.push(afterEachFunction); - } - }; - -})(jasmine.Env.prototype.afterEach); - - -jasmine.NestedResults.prototype.addResult = (function(addResult){ - - return function(result) { - addResult.call(this, result); - if (result.type != 'MessageResult' && !result.passed()) fail(result.message); - }; - -})(jasmine.NestedResults.prototype.addResult); - - -jstestdriver.plugins.TestRunnerPlugin.prototype.runTestConfiguration = (function(runTestConfiguration){ - - return function(testRunConfiguration, onTestDone, onTestRunConfigurationComplete){ - for (var i = 0, l = before.length; i < l; i++) before[i](); - onTestRunConfigurationComplete = (function(configurationComplete){ - - return function() { - for (var i = 0, l = after.length; i < l; i++) after[i](); - configurationComplete(); - }; - - })(onTestRunConfigurationComplete); - runTestConfiguration.call(this, testRunConfiguration, onTestDone, onTestRunConfigurationComplete); - }; - -})(jstestdriver.plugins.TestRunnerPlugin.prototype.runTestConfiguration); - - -// Reset environment with overriden methods. -jasmine.currentEnv_ = null; -jasmine.getEnv(); + function bind(_this, _function){ + return function(){ + return _function.call(_this); + } + } + + var currentFrame = frame(null, null); + + function frame(parent, name){ + var caseName = (parent && parent.caseName ? parent.caseName + " " : '') + (name ? name : ''); + var frame = { + name: name, + caseName: caseName, + parent: parent, + testCase: TestCase(caseName), + before: [], + after: [], + runBefore: function(){ + if (parent) parent.runBefore.apply(this); + for ( var i = 0; i < frame.before.length; i++) { + frame.before[i].apply(this); + } + }, + runAfter: function(){ + for ( var i = 0; i < frame.after.length; i++) { + frame.after[i].apply(this); + } + if (parent) parent.runAfter.apply(this); + } + }; + return frame; + }; + + jasmine.Env.prototype.describe = (function(describe){ + return function(description){ + currentFrame = frame(currentFrame, description); + var val = describe.apply(this, arguments); + currentFrame = currentFrame.parent; + return val; + }; + + })(jasmine.Env.prototype.describe); + + + jasmine.Env.prototype.it = (function(it){ + return function(desc, itFn){ + var self = this; + var spec = it.apply(this, arguments); + var currentSpec = this.currentSpec; + var frame = this.jstdFrame = currentFrame; + this.jstdFrame.testCase.prototype['test that it ' + desc] = function(){ + frame.runBefore.apply(currentSpec); + try { + itFn.apply(currentSpec); + } finally { + frame.runAfter.apply(currentSpec); + } + }; + return spec; + }; + + })(jasmine.Env.prototype.it); + + + jasmine.Env.prototype.beforeEach = (function(beforeEach){ + return function(beforeEachFunction) { + beforeEach.apply(this, arguments); + currentFrame.before.push(beforeEachFunction); + }; + + })(jasmine.Env.prototype.beforeEach); + + + jasmine.Env.prototype.afterEach = (function(afterEach){ + return function(afterEachFunction) { + afterEach.apply(this, arguments); + currentFrame.after.push(afterEachFunction); + }; + + })(jasmine.Env.prototype.afterEach); + + + jasmine.NestedResults.prototype.addResult = (function(addResult){ + return function(result) { + addResult.call(this, result); + if (result.type != 'MessageResult' && !result.passed()) fail(result.message); + }; + + })(jasmine.NestedResults.prototype.addResult); + + // Reset environment with overriden methods. + jasmine.currentEnv_ = null; + jasmine.getEnv(); })(); diff --git a/lib/jasmine/jasmine-0.10.1.js b/lib/jasmine/jasmine-0.10.1.js deleted file mode 100644 index f9bd7d6f..00000000 --- a/lib/jasmine/jasmine-0.10.1.js +++ /dev/null @@ -1,2276 +0,0 @@ -/** - * Top level namespace for Jasmine, a lightweight JavaScript BDD/spec/testing framework. - * - * @namespace - */ -var jasmine = {}; - -/** - * @private - */ -jasmine.unimplementedMethod_ = function() { - throw new Error("unimplemented method"); -}; - -/** - * Use jasmine.undefined instead of undefined, since undefined 0; -}; - -/** - * Returns a matchable 'generic' object of the class type. For use in expecations of type when values don't matter. - * - * @example - * // don't care about which function is passed in, as long as it's a function - * expect(mySpy).wasCalledWith(jasmine.any(Function)); - * - * @param {Class} clazz - * @returns matchable object of the type clazz - */ -jasmine.any = function(clazz) { - return new jasmine.Matchers.Any(clazz); -}; - -/** - * Jasmine Spies are test doubles that can act as stubs, spies, fakes or when used in an expecation, mocks. - * - * Spies should be created in test setup, before expectations. They can then be checked, using the standard Jasmine - * expectation syntax. Spies can be checked if they were called or not and what the calling params were. - * - * A Spy has the following mehtod: wasCalled, callCount, mostRecentCall, and argsForCall (see docs) - * Spies are torn down at the end of every spec. - * - * Note: Do not call new jasmine.Spy() directly - a spy must be created using spyOn, jasmine.createSpy or jasmine.createSpyObj. - * - * @example - * // a stub - * var myStub = jasmine.createSpy('myStub'); // can be used anywhere - * - * // spy example - * var foo = { - * not: function(bool) { return !bool; } - * } - * - * // actual foo.not will not be called, execution stops - * spyOn(foo, 'not'); - - // foo.not spied upon, execution will continue to implementation - * spyOn(foo, 'not').andCallThrough(); - * - * // fake example - * var foo = { - * not: function(bool) { return !bool; } - * } - * - * // foo.not(val) will return val - * spyOn(foo, 'not').andCallFake(function(value) {return value;}); - * - * // mock example - * foo.not(7 == 7); - * expect(foo.not).wasCalled(); - * expect(foo.not).wasCalledWith(true); - * - * @constructor - * @see spyOn, jasmine.createSpy, jasmine.createSpyObj - * @param {String} name - */ -jasmine.Spy = function(name) { - /** - * The name of the spy, if provided. - */ - this.identity = name || 'unknown'; - /** - * Is this Object a spy? - */ - this.isSpy = true; - /** - * The actual function this spy stubs. - */ - this.plan = function() { - }; - /** - * Tracking of the most recent call to the spy. - * @example - * var mySpy = jasmine.createSpy('foo'); - * mySpy(1, 2); - * mySpy.mostRecentCall.args = [1, 2]; - */ - this.mostRecentCall = {}; - - /** - * Holds arguments for each call to the spy, indexed by call count - * @example - * var mySpy = jasmine.createSpy('foo'); - * mySpy(1, 2); - * mySpy(7, 8); - * mySpy.mostRecentCall.args = [7, 8]; - * mySpy.argsForCall[0] = [1, 2]; - * mySpy.argsForCall[1] = [7, 8]; - */ - this.argsForCall = []; - this.calls = []; -}; - -/** - * Tells a spy to call through to the actual implemenatation. - * - * @example - * var foo = { - * bar: function() { // do some stuff } - * } - * - * // defining a spy on an existing property: foo.bar - * spyOn(foo, 'bar').andCallThrough(); - */ -jasmine.Spy.prototype.andCallThrough = function() { - this.plan = this.originalValue; - return this; -}; - -/** - * For setting the return value of a spy. - * - * @example - * // defining a spy from scratch: foo() returns 'baz' - * var foo = jasmine.createSpy('spy on foo').andReturn('baz'); - * - * // defining a spy on an existing property: foo.bar() returns 'baz' - * spyOn(foo, 'bar').andReturn('baz'); - * - * @param {Object} value - */ -jasmine.Spy.prototype.andReturn = function(value) { - this.plan = function() { - return value; - }; - return this; -}; - -/** - * For throwing an exception when a spy is called. - * - * @example - * // defining a spy from scratch: foo() throws an exception w/ message 'ouch' - * var foo = jasmine.createSpy('spy on foo').andThrow('baz'); - * - * // defining a spy on an existing property: foo.bar() throws an exception w/ message 'ouch' - * spyOn(foo, 'bar').andThrow('baz'); - * - * @param {String} exceptionMsg - */ -jasmine.Spy.prototype.andThrow = function(exceptionMsg) { - this.plan = function() { - throw exceptionMsg; - }; - return this; -}; - -/** - * Calls an alternate implementation when a spy is called. - * - * @example - * var baz = function() { - * // do some stuff, return something - * } - * // defining a spy from scratch: foo() calls the function baz - * var foo = jasmine.createSpy('spy on foo').andCall(baz); - * - * // defining a spy on an existing property: foo.bar() calls an anonymnous function - * spyOn(foo, 'bar').andCall(function() { return 'baz';} ); - * - * @param {Function} fakeFunc - */ -jasmine.Spy.prototype.andCallFake = function(fakeFunc) { - this.plan = fakeFunc; - return this; -}; - -/** - * Resets all of a spy's the tracking variables so that it can be used again. - * - * @example - * spyOn(foo, 'bar'); - * - * foo.bar(); - * - * expect(foo.bar.callCount).toEqual(1); - * - * foo.bar.reset(); - * - * expect(foo.bar.callCount).toEqual(0); - */ -jasmine.Spy.prototype.reset = function() { - this.wasCalled = false; - this.callCount = 0; - this.argsForCall = []; - this.calls = []; - this.mostRecentCall = {}; -}; - -jasmine.createSpy = function(name) { - - var spyObj = function() { - spyObj.wasCalled = true; - spyObj.callCount++; - var args = jasmine.util.argsToArray(arguments); - spyObj.mostRecentCall.object = this; - spyObj.mostRecentCall.args = args; - spyObj.argsForCall.push(args); - spyObj.calls.push({object: this, args: args}); - return spyObj.plan.apply(this, arguments); - }; - - var spy = new jasmine.Spy(name); - - for (var prop in spy) { - spyObj[prop] = spy[prop]; - } - - spyObj.reset(); - - return spyObj; -}; - -/** - * Determines whether an object is a spy. - * - * @param {jasmine.Spy|Object} putativeSpy - * @returns {Boolean} - */ -jasmine.isSpy = function(putativeSpy) { - return putativeSpy && putativeSpy.isSpy; -}; - -/** - * Creates a more complicated spy: an Object that has every property a function that is a spy. Used for stubbing something - * large in one call. - * - * @param {String} baseName name of spy class - * @param {Array} methodNames array of names of methods to make spies - */ -jasmine.createSpyObj = function(baseName, methodNames) { - if (!jasmine.isArray_(methodNames) || methodNames.length == 0) { - throw new Error('createSpyObj requires a non-empty array of method names to create spies for'); - } - var obj = {}; - for (var i = 0; i < methodNames.length; i++) { - obj[methodNames[i]] = jasmine.createSpy(baseName + '.' + methodNames[i]); - } - return obj; -}; - -jasmine.log = function(message) { - jasmine.getEnv().currentSpec.log(message); -}; - -/** - * Function that installs a spy on an existing object's method name. Used within a Spec to create a spy. - * - * @example - * // spy example - * var foo = { - * not: function(bool) { return !bool; } - * } - * spyOn(foo, 'not'); // actual foo.not will not be called, execution stops - * - * @see jasmine.createSpy - * @param obj - * @param methodName - * @returns a Jasmine spy that can be chained with all spy methods - */ -var spyOn = function(obj, methodName) { - return jasmine.getEnv().currentSpec.spyOn(obj, methodName); -}; - -/** - * Creates a Jasmine spec that will be added to the current suite. - * - * // TODO: pending tests - * - * @example - * it('should be true', function() { - * expect(true).toEqual(true); - * }); - * - * @param {String} desc description of this specification - * @param {Function} func defines the preconditions and expectations of the spec - */ -var it = function(desc, func) { - return jasmine.getEnv().it(desc, func); -}; - -/** - * Creates a disabled Jasmine spec. - * - * A convenience method that allows existing specs to be disabled temporarily during development. - * - * @param {String} desc description of this specification - * @param {Function} func defines the preconditions and expectations of the spec - */ -var xit = function(desc, func) { - return jasmine.getEnv().xit(desc, func); -}; - -/** - * Starts a chain for a Jasmine expectation. - * - * It is passed an Object that is the actual value and should chain to one of the many - * jasmine.Matchers functions. - * - * @param {Object} actual Actual value to test against and expected value - */ -var expect = function(actual) { - return jasmine.getEnv().currentSpec.expect(actual); -}; - -/** - * Defines part of a jasmine spec. Used in cominbination with waits or waitsFor in asynchrnous specs. - * - * @param {Function} func Function that defines part of a jasmine spec. - */ -var runs = function(func) { - jasmine.getEnv().currentSpec.runs(func); -}; - -/** - * Waits for a timeout before moving to the next runs()-defined block. - * @param {Number} timeout - */ -var waits = function(timeout) { - jasmine.getEnv().currentSpec.waits(timeout); -}; - -/** - * Waits for the latchFunction to return true before proceeding to the next runs()-defined block. - * - * @param {Number} timeout - * @param {Function} latchFunction - * @param {String} message - */ -var waitsFor = function(timeout, latchFunction, message) { - jasmine.getEnv().currentSpec.waitsFor(timeout, latchFunction, message); -}; - -/** - * A function that is called before each spec in a suite. - * - * Used for spec setup, including validating assumptions. - * - * @param {Function} beforeEachFunction - */ -var beforeEach = function(beforeEachFunction) { - jasmine.getEnv().beforeEach(beforeEachFunction); -}; - -/** - * A function that is called after each spec in a suite. - * - * Used for restoring any state that is hijacked during spec execution. - * - * @param {Function} afterEachFunction - */ -var afterEach = function(afterEachFunction) { - jasmine.getEnv().afterEach(afterEachFunction); -}; - -/** - * Defines a suite of specifications. - * - * Stores the description and all defined specs in the Jasmine environment as one suite of specs. Variables declared - * are accessible by calls to beforeEach, it, and afterEach. Describe blocks can be nested, allowing for specialization - * of setup in some tests. - * - * @example - * // TODO: a simple suite - * - * // TODO: a simple suite with a nested describe block - * - * @param {String} description A string, usually the class under test. - * @param {Function} specDefinitions function that defines several specs. - */ -var describe = function(description, specDefinitions) { - return jasmine.getEnv().describe(description, specDefinitions); -}; - -/** - * Disables a suite of specifications. Used to disable some suites in a file, or files, temporarily during development. - * - * @param {String} description A string, usually the class under test. - * @param {Function} specDefinitions function that defines several specs. - */ -var xdescribe = function(description, specDefinitions) { - return jasmine.getEnv().xdescribe(description, specDefinitions); -}; - - -// Provide the XMLHttpRequest class for IE 5.x-6.x: -jasmine.XmlHttpRequest = (typeof XMLHttpRequest == "undefined") ? function() { - try { - return new ActiveXObject("Msxml2.XMLHTTP.6.0"); - } catch(e) { - } - try { - return new ActiveXObject("Msxml2.XMLHTTP.3.0"); - } catch(e) { - } - try { - return new ActiveXObject("Msxml2.XMLHTTP"); - } catch(e) { - } - try { - return new ActiveXObject("Microsoft.XMLHTTP"); - } catch(e) { - } - throw new Error("This browser does not support XMLHttpRequest."); -} : XMLHttpRequest; - -/** - * Adds suite files to an HTML document so that they are executed, thus adding them to the current - * Jasmine environment. - * - * @param {String} url path to the file to include - * @param {Boolean} opt_global - */ -jasmine.include = function(url, opt_global) { - if (opt_global) { - document.write('