Rewrite Spec & allow Jasmine to be namespaced
- THere seems to be a performance regression. Large test suites may throw - Regressions: Mock Clock won't install correctly, async specs are temporarily not supported. - Async spec runs/waits interface is gone. Blocks are gone. - Move most global usage into jasmine.Env constructor. - Remove optional 'Jasmine running' from HtmlReporter -- caused NS_FACTORY_ERROR in firefox when tested
This commit is contained in:
@@ -1,27 +0,0 @@
|
||||
/**
|
||||
* Blocks are functions with executable code that make up a spec.
|
||||
*
|
||||
* @constructor
|
||||
* @param {jasmine.Env} env
|
||||
* @param {Function} func
|
||||
* @param {jasmine.Spec} spec
|
||||
*/
|
||||
jasmine.Block = function(env, func, spec) {
|
||||
this.env = env;
|
||||
this.func = func;
|
||||
this.spec = spec;
|
||||
};
|
||||
|
||||
jasmine.Block.prototype.execute = function(onComplete) {
|
||||
if (!jasmine.CATCH_EXCEPTIONS) {
|
||||
this.func.apply(this.spec);
|
||||
}
|
||||
else {
|
||||
try {
|
||||
this.func.apply(this.spec);
|
||||
} catch (e) {
|
||||
this.spec.fail(e);
|
||||
}
|
||||
}
|
||||
onComplete();
|
||||
};
|
||||
176
src/core/Env.js
176
src/core/Env.js
@@ -4,15 +4,18 @@
|
||||
* @constructor
|
||||
*/
|
||||
(function() {
|
||||
|
||||
function createSpec(env, suite, description) {
|
||||
return new jasmine.Spec(env, suite, description);
|
||||
}
|
||||
|
||||
jasmine.Env = function() {
|
||||
var self = this;
|
||||
var suiteConstructor = jasmine.Suite;
|
||||
var isSuite = function(thing) {
|
||||
return thing instanceof suiteConstructor;
|
||||
}
|
||||
this.jasmine = jasmine;
|
||||
this.currentRunner_ = new jasmine.Runner(this, isSuite);
|
||||
this.spies_ = [];
|
||||
this.currentSpec = null;
|
||||
this.currentSuite = null;
|
||||
this.currentRunner_ = new jasmine.Runner(this);
|
||||
this.catchExceptions = jasmine.CATCH_EXCEPTIONS;
|
||||
this.undefined = jasmine.undefined;
|
||||
|
||||
this.reporter = new jasmine.MultiReporter();
|
||||
|
||||
@@ -34,6 +37,90 @@
|
||||
jasmine.util.inherit(this.matchersClass, jasmine.Matchers);
|
||||
|
||||
jasmine.Matchers.wrapInto_(jasmine.Matchers.prototype, this.matchersClass);
|
||||
|
||||
var expectationFactory = function(actual, spec) {
|
||||
var expect = new (self.matchersClass)(self, actual, spec);
|
||||
expect.not = new (self.matchersClass)(self, actual, spec, true);
|
||||
return expect;
|
||||
};
|
||||
|
||||
var startCallback = function(spec) {
|
||||
self.currentSpec = spec;
|
||||
self.reporter.reportSpecStarting(spec);
|
||||
};
|
||||
|
||||
var beforeFns = function(currentSuite) {
|
||||
return function() {
|
||||
var befores = [];
|
||||
for (var suite = currentSuite; suite; suite = suite.parentSuite) {
|
||||
befores = befores.concat(suite.before_)
|
||||
}
|
||||
return befores.concat(self.currentRunner_.before_).reverse();
|
||||
}
|
||||
};
|
||||
|
||||
var afterFns = function(currentSuite) {
|
||||
return function() {
|
||||
var afters = [];
|
||||
for (var suite = currentSuite; suite; suite = suite.parentSuite) {
|
||||
afters = afters.concat(suite.after_)
|
||||
}
|
||||
return afters.concat(self.currentRunner_.after_)
|
||||
}
|
||||
};
|
||||
|
||||
var exceptionFormatter = jasmine.util.formatException;
|
||||
|
||||
var specConstructor = jasmine.Spec;
|
||||
|
||||
// TODO: this deserves a better name (not a Factory the way others are)
|
||||
var fullNameFactory = function(spec, currentSuite) {
|
||||
var descriptions = [];
|
||||
for (var suite = currentSuite; suite; suite = suite.parentSuite) {
|
||||
descriptions.push(suite.description)
|
||||
}
|
||||
descriptions.push(spec.description);
|
||||
return descriptions.join(' ') + '.';
|
||||
};
|
||||
|
||||
var buildExpectationResult = jasmine.buildExpectationResult;
|
||||
var expectationResultFactory = function(attrs) {
|
||||
return buildExpectationResult(attrs);
|
||||
};
|
||||
|
||||
this.specFactory = function(description, fn, suite) {
|
||||
var spec = new specConstructor({
|
||||
id: self.nextSpecId(),
|
||||
beforeFns: beforeFns(suite),
|
||||
afterFns: afterFns(suite),
|
||||
expectationFactory: expectationFactory,
|
||||
exceptionFormatter: exceptionFormatter,
|
||||
//TODO: move spec creation to more appropriate level and remove this shim
|
||||
resultCallback: function(result) { self.currentSpec = null; suite.specComplete(result); },
|
||||
fullNameFactory: function(spec) { return fullNameFactory(spec, suite) },
|
||||
startCallback: startCallback,
|
||||
description: description,
|
||||
catchExceptions: self.catchExceptions,
|
||||
expectationResultFactory: expectationResultFactory,
|
||||
fn: fn
|
||||
});
|
||||
|
||||
if (!self.specFilter(spec)) {
|
||||
spec.disable();
|
||||
}
|
||||
|
||||
return spec;
|
||||
};
|
||||
|
||||
|
||||
var queueConstructor = jasmine.Queue;
|
||||
var queueFactory = function() {
|
||||
return new queueConstructor(self);
|
||||
};
|
||||
this.suiteFactory = function(description, specDefinitions) {
|
||||
return new suiteConstructor(self, description, specDefinitions, self.currentSuite, queueFactory, isSuite);
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -42,22 +129,69 @@
|
||||
jasmine.Env.prototype.setInterval = jasmine.setInterval;
|
||||
jasmine.Env.prototype.clearInterval = jasmine.clearInterval;
|
||||
|
||||
//TODO: shim Spec addMatchers behavior into Env. Should be rewritten to remove globals, etc.
|
||||
jasmine.Env.prototype.addMatchers = function(matchersPrototype) {
|
||||
var parent = this.matchersClass;
|
||||
var newMatchersClass = function() {
|
||||
parent.apply(this, arguments);
|
||||
};
|
||||
jasmine.util.inherit(newMatchersClass, parent);
|
||||
jasmine.Matchers.wrapInto_(matchersPrototype, newMatchersClass);
|
||||
this.matchersClass = newMatchersClass;
|
||||
};
|
||||
/**
|
||||
* @returns an object containing jasmine version build info, if set.
|
||||
*/
|
||||
jasmine.Env.prototype.version = function () {
|
||||
if (jasmine.version_) {
|
||||
return jasmine.version_;
|
||||
if (this.jasmine.version_) {
|
||||
return this.jasmine.version_;
|
||||
} else {
|
||||
throw new Error('Version not set');
|
||||
}
|
||||
};
|
||||
|
||||
jasmine.Env.prototype.expect = function(actual) {
|
||||
return this.currentSpec.expect(actual);
|
||||
};
|
||||
|
||||
jasmine.Env.prototype.spyOn = function(obj, methodName) {
|
||||
if (obj == this.undefined) {
|
||||
throw "spyOn could not find an object to spy upon for " + methodName + "()";
|
||||
}
|
||||
|
||||
if (obj[methodName] === this.undefined) {
|
||||
throw methodName + '() method does not exist';
|
||||
}
|
||||
|
||||
if (obj[methodName] && obj[methodName].isSpy) {
|
||||
//TODO?: should this return the current spy? Downside: may cause user confusion about spy state
|
||||
throw new Error(methodName + ' has already been spied upon');
|
||||
}
|
||||
|
||||
var spyObj = jasmine.createSpy(methodName);
|
||||
|
||||
this.spies_.push(spyObj);
|
||||
spyObj.baseObj = obj;
|
||||
spyObj.methodName = methodName;
|
||||
spyObj.originalValue = obj[methodName];
|
||||
|
||||
obj[methodName] = spyObj;
|
||||
|
||||
return spyObj;
|
||||
};
|
||||
|
||||
jasmine.Env.prototype.removeAllSpies = function() {
|
||||
for (var i = 0; i < this.spies_.length; i++) {
|
||||
var spy = this.spies_[i];
|
||||
spy.baseObj[spy.methodName] = spy.originalValue;
|
||||
}
|
||||
this.spies_ = [];
|
||||
};
|
||||
/**
|
||||
* @returns string containing jasmine version build info, if set.
|
||||
*/
|
||||
jasmine.Env.prototype.versionString = function() {
|
||||
if (!jasmine.version_) {
|
||||
if (!this.jasmine.version_) {
|
||||
return "version unknown";
|
||||
}
|
||||
|
||||
@@ -97,13 +231,13 @@
|
||||
};
|
||||
|
||||
jasmine.Env.prototype.describe = function(description, specDefinitions) {
|
||||
var suite = new jasmine.Suite(this, description, specDefinitions, this.currentSuite);
|
||||
var suite = this.suiteFactory(description, specDefinitions);
|
||||
|
||||
var parentSuite = this.currentSuite;
|
||||
if (parentSuite) {
|
||||
parentSuite.add(suite);
|
||||
} else {
|
||||
this.currentRunner_.add(suite);
|
||||
this.currentRunner_.addSuite(suite);
|
||||
}
|
||||
|
||||
this.currentSuite = suite;
|
||||
@@ -154,15 +288,9 @@
|
||||
};
|
||||
};
|
||||
|
||||
jasmine.Env.prototype.it = function(description, func) {
|
||||
var spec = createSpec(this, this.currentSuite, description);
|
||||
jasmine.Env.prototype.it = function(description, fn) {
|
||||
var spec = this.specFactory(description, fn, this.currentSuite);
|
||||
this.currentSuite.add(spec);
|
||||
this.currentSpec = spec;
|
||||
|
||||
if (func) {
|
||||
spec.runs(func);
|
||||
}
|
||||
|
||||
return spec;
|
||||
};
|
||||
|
||||
@@ -202,7 +330,7 @@
|
||||
b.__Jasmine_been_here_before__ = a;
|
||||
|
||||
var hasKey = function(obj, keyName) {
|
||||
return obj !== null && obj[keyName] !== jasmine.undefined;
|
||||
return obj !== null && obj[keyName] !== this.undefined;
|
||||
};
|
||||
|
||||
for (var property in b) {
|
||||
@@ -238,13 +366,13 @@
|
||||
for (var i = 0; i < this.equalityTesters_.length; i++) {
|
||||
var equalityTester = this.equalityTesters_[i];
|
||||
var result = equalityTester(a, b, this, mismatchKeys, mismatchValues);
|
||||
if (result !== jasmine.undefined) return result;
|
||||
if (result !== this.undefined) return result;
|
||||
}
|
||||
|
||||
if (a === b) return true;
|
||||
|
||||
if (a === jasmine.undefined || a === null || b === jasmine.undefined || b === null) {
|
||||
return (a == jasmine.undefined && b == jasmine.undefined);
|
||||
if (a === this.undefined || a === null || b === this.undefined || b === null) {
|
||||
return (a == this.undefined && b == this.undefined);
|
||||
}
|
||||
|
||||
if (jasmine.isDomNode(a) && jasmine.isDomNode(b)) {
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
jasmine.JsApiReporter = function() {
|
||||
jasmine.JsApiReporter = function(jasmine) {
|
||||
this.jasmine = jasmine || {};
|
||||
this.started = false;
|
||||
this.finished = false;
|
||||
this.suites_ = [];
|
||||
@@ -23,7 +24,7 @@ jasmine.JsApiReporter.prototype.suites = function() {
|
||||
};
|
||||
|
||||
jasmine.JsApiReporter.prototype.summarize_ = function(suiteOrSpec) {
|
||||
var isSuite = suiteOrSpec instanceof jasmine.Suite;
|
||||
var isSuite = suiteOrSpec instanceof this.jasmine.Suite;
|
||||
var summary = {
|
||||
id: suiteOrSpec.id,
|
||||
name: suiteOrSpec.description,
|
||||
@@ -44,10 +45,6 @@ jasmine.JsApiReporter.prototype.results = function() {
|
||||
return this.results_;
|
||||
};
|
||||
|
||||
jasmine.JsApiReporter.prototype.resultsForSpec = function(specId) {
|
||||
return this.results_[specId];
|
||||
};
|
||||
|
||||
//noinspection JSUnusedLocalSymbols
|
||||
jasmine.JsApiReporter.prototype.reportRunnerResults = function(runner) {
|
||||
this.finished = true;
|
||||
@@ -58,10 +55,11 @@ jasmine.JsApiReporter.prototype.reportSuiteResults = function(suite) {
|
||||
};
|
||||
|
||||
//noinspection JSUnusedLocalSymbols
|
||||
jasmine.JsApiReporter.prototype.reportSpecResults = function(spec) {
|
||||
this.results_[spec.id] = {
|
||||
messages: spec.results().getItems(),
|
||||
result: spec.results().failedCount > 0 ? "failed" : "passed"
|
||||
jasmine.JsApiReporter.prototype.reportSpecResults = function(result) {
|
||||
this.results_[result.id] = {
|
||||
messages: result.failedExpectations,
|
||||
//result is status
|
||||
result: result.status
|
||||
};
|
||||
};
|
||||
|
||||
@@ -69,6 +67,7 @@ jasmine.JsApiReporter.prototype.reportSpecResults = function(spec) {
|
||||
jasmine.JsApiReporter.prototype.log = function(str) {
|
||||
};
|
||||
|
||||
//TODO: make work with new presenter.
|
||||
jasmine.JsApiReporter.prototype.resultsForSpecs = function(specIds){
|
||||
var results = {};
|
||||
for (var i = 0; i < specIds.length; i++) {
|
||||
@@ -83,14 +82,16 @@ jasmine.JsApiReporter.prototype.summarizeResult_ = function(result){
|
||||
var messagesLength = result.messages.length;
|
||||
for (var messageIndex = 0; messageIndex < messagesLength; messageIndex++) {
|
||||
var resultMessage = result.messages[messageIndex];
|
||||
//TODO: use result presenter here, not a bunch of spec crap
|
||||
summaryMessages.push({
|
||||
text: resultMessage.type == 'log' ? resultMessage.toString() : jasmine.undefined,
|
||||
//TODO: remove text.
|
||||
text: resultMessage.type == 'log' ? resultMessage.toString() : this.jasmine.undefined,
|
||||
//TODO: wat? in theory this is saying non-expect results should always be considered passed, but that's weird.
|
||||
passed: resultMessage.passed || true,
|
||||
passed: resultMessage.passed || true, //status === 'passed'
|
||||
type: resultMessage.type,
|
||||
message: resultMessage.message,
|
||||
trace: {
|
||||
stack: !resultMessage.passed ? resultMessage.trace.stack : jasmine.undefined
|
||||
stack: !resultMessage.passed ? resultMessage.trace.stack : this.jasmine.undefined
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
* @param {jasmine.Spec} spec
|
||||
*/
|
||||
jasmine.Matchers = function(env, actual, spec, opt_isNot) {
|
||||
//TODO: true dependency: equals, contains
|
||||
this.env = env;
|
||||
this.actual = actual;
|
||||
this.spec = spec;
|
||||
@@ -16,6 +17,7 @@ jasmine.Matchers.pp = function(str) {
|
||||
throw new Error("jasmine.Matchers.pp() is no longer supported, please use jasmine.pp() instead!");
|
||||
};
|
||||
|
||||
|
||||
jasmine.Matchers.wrapInto_ = function(prototype, matchersClass) {
|
||||
for (var methodName in prototype) {
|
||||
var orig = prototype[methodName];
|
||||
@@ -58,7 +60,7 @@ jasmine.Matchers.matcherFn_ = function(matcherName, matcherFunction) {
|
||||
actual: this.actual,
|
||||
message: message
|
||||
});
|
||||
this.spec.addMatcherResult(expectationResult);
|
||||
this.spec.addExpectationResult(result, expectationResult);
|
||||
return jasmine.undefined;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -12,7 +12,7 @@ jasmine.Queue = function(env) {
|
||||
};
|
||||
|
||||
jasmine.Queue.prototype.addBefore = function(block, ensure) {
|
||||
if (ensure === jasmine.undefined) {
|
||||
if (ensure === this.env.undefined) {
|
||||
ensure = false;
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ jasmine.Queue.prototype.addBefore = function(block, ensure) {
|
||||
};
|
||||
|
||||
jasmine.Queue.prototype.add = function(block, ensure) {
|
||||
if (ensure === jasmine.undefined) {
|
||||
if (ensure === this.env.undefined) {
|
||||
ensure = false;
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ jasmine.Queue.prototype.add = function(block, ensure) {
|
||||
};
|
||||
|
||||
jasmine.Queue.prototype.insertNext = function(block, ensure) {
|
||||
if (ensure === jasmine.undefined) {
|
||||
if (ensure === this.env.undefined) {
|
||||
ensure = false;
|
||||
}
|
||||
|
||||
@@ -51,50 +51,55 @@ jasmine.Queue.prototype.isRunning = function() {
|
||||
|
||||
jasmine.Queue.LOOP_DONT_RECURSE = true;
|
||||
|
||||
jasmine.Queue.prototype.incrementQueue = function() {
|
||||
if (this.blocks[this.index].abort) {
|
||||
this.abort = true;
|
||||
}
|
||||
this.offset = 0;
|
||||
this.index++;
|
||||
this.next_();
|
||||
}
|
||||
|
||||
jasmine.Queue.prototype.next_ = function() {
|
||||
var self = this;
|
||||
var goAgain = true;
|
||||
// var goAgain = true;
|
||||
|
||||
while (goAgain) {
|
||||
goAgain = false;
|
||||
// while (goAgain) {
|
||||
// goAgain = false;
|
||||
|
||||
if (self.index < self.blocks.length && !(this.abort && !this.ensured[self.index])) {
|
||||
var calledSynchronously = true;
|
||||
var completedSynchronously = false;
|
||||
// var calledSynchronously = true;
|
||||
// var completedSynchronously = false;
|
||||
|
||||
var onComplete = function () {
|
||||
if (jasmine.Queue.LOOP_DONT_RECURSE && calledSynchronously) {
|
||||
completedSynchronously = true;
|
||||
return;
|
||||
}
|
||||
// var onComplete = function () {
|
||||
// if (jasmine.Queue.LOOP_DONT_RECURSE && calledSynchronously) {
|
||||
// completedSynchronously = true;
|
||||
// return;
|
||||
// }
|
||||
|
||||
if (self.blocks[self.index].abort) {
|
||||
self.abort = true;
|
||||
}
|
||||
self.blocks[self.index].execute(function() { self.incrementQueue() });
|
||||
|
||||
self.offset = 0;
|
||||
self.index++;
|
||||
|
||||
var now = new Date().getTime();
|
||||
if (self.env.updateInterval && now - self.env.lastUpdate > self.env.updateInterval) {
|
||||
self.env.lastUpdate = now;
|
||||
self.env.setTimeout(function() {
|
||||
self.next_();
|
||||
}, 0);
|
||||
} else {
|
||||
if (jasmine.Queue.LOOP_DONT_RECURSE && completedSynchronously) {
|
||||
goAgain = true;
|
||||
} else {
|
||||
self.next_();
|
||||
}
|
||||
}
|
||||
};
|
||||
self.blocks[self.index].execute(onComplete);
|
||||
// var now = new Date().getTime();
|
||||
// if (self.env.updateInterval && now - self.env.lastUpdate > self.env.updateInterval) {
|
||||
// self.env.lastUpdate = now;
|
||||
// self.env.setTimeout(function() {
|
||||
// self.next_();
|
||||
// }, 0);
|
||||
// } else {
|
||||
// if (jasmine.Queue.LOOP_DONT_RECURSE && completedSynchronously) {
|
||||
// goAgain = true;
|
||||
// } else {
|
||||
// self.next_();
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
// self.blocks[self.index].execute(function() { self.next_(); });
|
||||
|
||||
calledSynchronously = false;
|
||||
if (completedSynchronously) {
|
||||
onComplete();
|
||||
}
|
||||
// calledSynchronously = false;
|
||||
// if (completedSynchronously) {
|
||||
// onComplete();
|
||||
// }
|
||||
|
||||
} else {
|
||||
self.running = false;
|
||||
@@ -102,5 +107,5 @@ jasmine.Queue.prototype.next_ = function() {
|
||||
self.onComplete();
|
||||
}
|
||||
}
|
||||
}
|
||||
// }
|
||||
};
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
//TODO: runner is a special case of suite.
|
||||
/**
|
||||
* Runner
|
||||
*
|
||||
* @constructor
|
||||
* @param {jasmine.Env} env
|
||||
*/
|
||||
jasmine.Runner = function(env) {
|
||||
jasmine.Runner = function(env, isSuite) {
|
||||
var self = this;
|
||||
self.env = env;
|
||||
self.queue = new jasmine.Queue(env);
|
||||
self.before_ = [];
|
||||
self.after_ = [];
|
||||
self.suites_ = [];
|
||||
self.isSuite = isSuite || function() {};
|
||||
};
|
||||
|
||||
jasmine.Runner.prototype.execute = function() {
|
||||
@@ -40,13 +42,18 @@ jasmine.Runner.prototype.finishCallback = function() {
|
||||
|
||||
jasmine.Runner.prototype.addSuite = function(suite) {
|
||||
this.suites_.push(suite);
|
||||
this.queue.add(suite);
|
||||
};
|
||||
|
||||
|
||||
//TODO: runner should die a slow unhappy death.
|
||||
//Nobody should ever call instanceof.
|
||||
jasmine.Runner.prototype.add = function(block) {
|
||||
if (block instanceof jasmine.Suite) {
|
||||
if (this.isSuite(block)) {
|
||||
this.addSuite(block);
|
||||
} else {
|
||||
this.queue.add(block);
|
||||
}
|
||||
this.queue.add(block);
|
||||
};
|
||||
|
||||
jasmine.Runner.prototype.specs = function () {
|
||||
|
||||
294
src/core/Spec.js
294
src/core/Spec.js
@@ -1,243 +1,97 @@
|
||||
/**
|
||||
* Internal representation of a Jasmine specification, or test.
|
||||
*
|
||||
* @constructor
|
||||
* @param {jasmine.Env} env
|
||||
* @param {jasmine.Suite} suite
|
||||
* @param {String} description
|
||||
*/
|
||||
jasmine.Spec = function(env, suite, description) {
|
||||
if (!env) {
|
||||
throw new Error('jasmine.Env() required');
|
||||
jasmine.Spec = function(attrs) {
|
||||
this.failedExpectations = [];
|
||||
this.encounteredExpectations = false;
|
||||
this.expectationFactory = attrs.expectationFactory;
|
||||
this.resultCallback = attrs.resultCallback || function() {};
|
||||
this.id = attrs.id;
|
||||
this.description = attrs.description;
|
||||
this.fn = attrs.fn;
|
||||
this.beforeFns = attrs.beforeFns || function() {};
|
||||
this.afterFns = attrs.afterFns || function() {};
|
||||
this.catchExceptions = attrs.catchExceptions;
|
||||
this.startCallback = attrs.startCallback || function() {};
|
||||
this.exceptionFormatter = attrs.exceptionFormatter || function() {};
|
||||
this.fullNameFactory = attrs.fullNameFactory;
|
||||
this.expectationResultFactory = attrs.expectationResultFactory || function() {};
|
||||
};
|
||||
|
||||
jasmine.Spec.prototype.addExpectationResult = function(passed, data) {
|
||||
this.encounteredExpectations = true;
|
||||
if (!passed) {
|
||||
this.failedExpectations.push(data);
|
||||
}
|
||||
if (!suite) {
|
||||
throw new Error('jasmine.Suite() required');
|
||||
}
|
||||
var spec = this;
|
||||
spec.id = env.nextSpecId ? env.nextSpecId() : null;
|
||||
spec.env = env;
|
||||
spec.suite = suite;
|
||||
spec.description = description;
|
||||
spec.queue = new jasmine.Queue(env);
|
||||
|
||||
spec.afterCallbacks = [];
|
||||
spec.spies_ = [];
|
||||
|
||||
spec.results_ = new jasmine.NestedResults();
|
||||
spec.results_.description = description;
|
||||
spec.matchersClass = null;
|
||||
};
|
||||
|
||||
jasmine.Spec.prototype.getFullName = function() {
|
||||
return this.suite.getFullName() + ' ' + this.description + '.';
|
||||
};
|
||||
|
||||
|
||||
jasmine.Spec.prototype.results = function() {
|
||||
return this.results_;
|
||||
};
|
||||
|
||||
/**
|
||||
* All parameters are pretty-printed and concatenated together, then written to the spec's output.
|
||||
*
|
||||
* Be careful not to leave calls to <code>jasmine.log</code> in production code.
|
||||
*/
|
||||
jasmine.Spec.prototype.log = function() {
|
||||
return this.results_.log(arguments);
|
||||
};
|
||||
|
||||
jasmine.Spec.prototype.runs = function (func) {
|
||||
var block = new jasmine.Block(this.env, func, this);
|
||||
this.addToQueue(block);
|
||||
return this;
|
||||
};
|
||||
|
||||
jasmine.Spec.prototype.addToQueue = function (block) {
|
||||
if (this.queue.isRunning()) {
|
||||
this.queue.insertNext(block);
|
||||
} else {
|
||||
this.queue.add(block);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {jasmine.ExpectationResult} result
|
||||
*/
|
||||
jasmine.Spec.prototype.addMatcherResult = function(result) {
|
||||
this.results_.addResult(result);
|
||||
};
|
||||
|
||||
jasmine.Spec.prototype.expect = function(actual) {
|
||||
var positive = new (this.getMatchersClass_())(this.env, actual, this);
|
||||
positive.not = new (this.getMatchersClass_())(this.env, actual, this, true);
|
||||
return positive;
|
||||
return this.expectationFactory(actual, this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Waits a fixed time period before moving to the next block.
|
||||
*
|
||||
* @deprecated Use waitsFor() instead
|
||||
* @param {Number} timeout milliseconds to wait
|
||||
*/
|
||||
jasmine.Spec.prototype.waits = function(timeout) {
|
||||
var waitsFunc = new jasmine.WaitsBlock(this.env, timeout, this);
|
||||
this.addToQueue(waitsFunc);
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Waits for the latchFunction to return true before proceeding to the next block.
|
||||
*
|
||||
* @param {Function} latchFunction
|
||||
* @param {String} optional_timeoutMessage
|
||||
* @param {Number} optional_timeout
|
||||
*/
|
||||
jasmine.Spec.prototype.waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) {
|
||||
var latchFunction_ = null;
|
||||
var optional_timeoutMessage_ = null;
|
||||
var optional_timeout_ = null;
|
||||
|
||||
for (var i = 0; i < arguments.length; i++) {
|
||||
var arg = arguments[i];
|
||||
switch (typeof arg) {
|
||||
case 'function':
|
||||
latchFunction_ = arg;
|
||||
break;
|
||||
case 'string':
|
||||
optional_timeoutMessage_ = arg;
|
||||
break;
|
||||
case 'number':
|
||||
optional_timeout_ = arg;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var waitsForFunc = new jasmine.WaitsForBlock(this.env, optional_timeout_, latchFunction_, optional_timeoutMessage_, this);
|
||||
this.addToQueue(waitsForFunc);
|
||||
return this;
|
||||
};
|
||||
|
||||
jasmine.Spec.prototype.fail = function (e) {
|
||||
var expectationResult = jasmine.buildExpectationResult({
|
||||
passed: false,
|
||||
message: e ? jasmine.util.formatException(e) : 'Exception',
|
||||
trace: { stack: e.stack }
|
||||
});
|
||||
this.results_.addResult(expectationResult);
|
||||
};
|
||||
|
||||
jasmine.Spec.prototype.getMatchersClass_ = function() {
|
||||
return this.matchersClass || this.env.matchersClass;
|
||||
};
|
||||
|
||||
jasmine.Spec.prototype.addMatchers = function(matchersPrototype) {
|
||||
var parent = this.getMatchersClass_();
|
||||
var newMatchersClass = function() {
|
||||
parent.apply(this, arguments);
|
||||
};
|
||||
jasmine.util.inherit(newMatchersClass, parent);
|
||||
jasmine.Matchers.wrapInto_(matchersPrototype, newMatchersClass);
|
||||
this.matchersClass = newMatchersClass;
|
||||
};
|
||||
|
||||
jasmine.Spec.prototype.finishCallback = function() {
|
||||
this.env.reporter.reportSpecResults(this);
|
||||
};
|
||||
|
||||
jasmine.Spec.prototype.finish = function(onComplete) {
|
||||
this.removeAllSpies();
|
||||
this.finishCallback();
|
||||
if (onComplete) {
|
||||
onComplete();
|
||||
}
|
||||
};
|
||||
|
||||
jasmine.Spec.prototype.after = function(doAfter) {
|
||||
if (this.queue.isRunning()) {
|
||||
this.queue.add(new jasmine.Block(this.env, doAfter, this), true);
|
||||
} else {
|
||||
this.afterCallbacks.unshift(doAfter);
|
||||
}
|
||||
};
|
||||
|
||||
jasmine.Spec.prototype.execute = function(onComplete) {
|
||||
var spec = this;
|
||||
if (!spec.env.specFilter(spec)) {
|
||||
spec.results_.skipped = true;
|
||||
spec.finish(onComplete);
|
||||
jasmine.Spec.prototype.execute = function() {
|
||||
if (this.disabled) {
|
||||
resultCallback.call(this);
|
||||
return;
|
||||
}
|
||||
|
||||
this.env.reporter.reportSpecStarting(this);
|
||||
|
||||
spec.env.currentSpec = spec;
|
||||
|
||||
spec.addBeforesAndAftersToQueue();
|
||||
|
||||
spec.queue.start(function () {
|
||||
spec.finish(onComplete);
|
||||
});
|
||||
};
|
||||
|
||||
jasmine.Spec.prototype.addBeforesAndAftersToQueue = function() {
|
||||
var runner = this.env.currentRunner();
|
||||
var i;
|
||||
|
||||
for (var suite = this.suite; suite; suite = suite.parentSuite) {
|
||||
for (i = 0; i < suite.before_.length; i++) {
|
||||
this.queue.addBefore(new jasmine.Block(this.env, suite.before_[i], this));
|
||||
var befores = this.beforeFns() || [],
|
||||
afters = this.afterFns() || [];
|
||||
this.startCallback(this);
|
||||
try {
|
||||
for (var i = 0; i < befores.length; i++) {
|
||||
befores[i].call(this);
|
||||
}
|
||||
this.fn.call(this);
|
||||
for (i = 0; i < afters.length; i++) {
|
||||
afters[i].call(this);
|
||||
}
|
||||
} catch (e) {
|
||||
//TODO: weird. buildExpectationResult is really a presenter for expectations
|
||||
//so this should take an expectation object.
|
||||
this.addExpectationResult(false, this.expectationResultFactory({
|
||||
matcherName: "",
|
||||
passed: false,
|
||||
expected: "",
|
||||
actual: "",
|
||||
message: this.exceptionFormatter(e),
|
||||
trace: e
|
||||
}));
|
||||
if (!this.catchExceptions) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < runner.before_.length; i++) {
|
||||
this.queue.addBefore(new jasmine.Block(this.env, runner.before_[i], this));
|
||||
finally {
|
||||
resultCallback.call(this);
|
||||
}
|
||||
for (i = 0; i < this.afterCallbacks.length; i++) {
|
||||
this.queue.add(new jasmine.Block(this.env, this.afterCallbacks[i], this), true);
|
||||
}
|
||||
for (suite = this.suite; suite; suite = suite.parentSuite) {
|
||||
for (i = 0; i < suite.after_.length; i++) {
|
||||
this.queue.add(new jasmine.Block(this.env, suite.after_[i], this), true);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < runner.after_.length; i++) {
|
||||
this.queue.add(new jasmine.Block(this.env, runner.after_[i], this), true);
|
||||
|
||||
function resultCallback() {
|
||||
this.resultCallback({
|
||||
id: this.id,
|
||||
status: this.status(),
|
||||
description: this.description,
|
||||
failedExpectations: this.failedExpectations
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
jasmine.Spec.prototype.explodes = function() {
|
||||
throw 'explodes function should not have been called';
|
||||
jasmine.Spec.prototype.disable = function() {
|
||||
this.disabled = true;
|
||||
};
|
||||
|
||||
jasmine.Spec.prototype.spyOn = function(obj, methodName, ignoreMethodDoesntExist) {
|
||||
if (obj == jasmine.undefined) {
|
||||
throw "spyOn could not find an object to spy upon for " + methodName + "()";
|
||||
jasmine.Spec.prototype.status = function() {
|
||||
if (this.disabled) {
|
||||
return 'disabled';
|
||||
}
|
||||
|
||||
if (!ignoreMethodDoesntExist && obj[methodName] === jasmine.undefined) {
|
||||
throw methodName + '() method does not exist';
|
||||
if (!this.encounteredExpectations) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!ignoreMethodDoesntExist && obj[methodName] && obj[methodName].isSpy) {
|
||||
throw new Error(methodName + ' has already been spied upon');
|
||||
if (this.failedExpectations.length > 0) {
|
||||
return 'failed';
|
||||
} else {
|
||||
return 'passed';
|
||||
}
|
||||
|
||||
var spyObj = jasmine.createSpy(methodName);
|
||||
|
||||
this.spies_.push(spyObj);
|
||||
spyObj.baseObj = obj;
|
||||
spyObj.methodName = methodName;
|
||||
spyObj.originalValue = obj[methodName];
|
||||
|
||||
obj[methodName] = spyObj;
|
||||
|
||||
return spyObj;
|
||||
};
|
||||
|
||||
jasmine.Spec.prototype.removeAllSpies = function() {
|
||||
for (var i = 0; i < this.spies_.length; i++) {
|
||||
var spy = this.spies_[i];
|
||||
spy.baseObj[spy.methodName] = spy.originalValue;
|
||||
}
|
||||
this.spies_ = [];
|
||||
};
|
||||
|
||||
//TODO: remove
|
||||
jasmine.Spec.prototype.getFullName = function() {
|
||||
return this.fullNameFactory(this);
|
||||
}
|
||||
|
||||
@@ -7,13 +7,16 @@
|
||||
* @param {Function} specDefinitions
|
||||
* @param {jasmine.Suite} parentSuite
|
||||
*/
|
||||
jasmine.Suite = function(env, description, specDefinitions, parentSuite) {
|
||||
jasmine.Suite = function(env, description, specDefinitions, parentSuite, queueFactory, isSuite) {
|
||||
var self = this;
|
||||
//TODO: remove once we unit test Suite
|
||||
var queueFactory = queueFactory || function() {};
|
||||
self.id = env.nextSuiteId ? env.nextSuiteId() : null;
|
||||
self.description = description;
|
||||
self.queue = new jasmine.Queue(env);
|
||||
self.queue = queueFactory();
|
||||
self.parentSuite = parentSuite;
|
||||
self.env = env;
|
||||
self.isSuite = isSuite || function() {};
|
||||
self.before_ = [];
|
||||
self.after_ = [];
|
||||
self.children_ = [];
|
||||
@@ -47,9 +50,10 @@ jasmine.Suite.prototype.afterEach = function(afterEachFunction) {
|
||||
this.after_.unshift(afterEachFunction);
|
||||
};
|
||||
|
||||
//TODO: interface should be addSpec or addSuite methods.
|
||||
jasmine.Suite.prototype.add = function(suiteOrSpec) {
|
||||
this.children_.push(suiteOrSpec);
|
||||
if (suiteOrSpec instanceof jasmine.Suite) {
|
||||
if (this.isSuite(suiteOrSpec)) {
|
||||
this.suites_.push(suiteOrSpec);
|
||||
this.env.currentRunner().addSuite(suiteOrSpec);
|
||||
} else {
|
||||
@@ -58,6 +62,14 @@ jasmine.Suite.prototype.add = function(suiteOrSpec) {
|
||||
this.queue.add(suiteOrSpec);
|
||||
};
|
||||
|
||||
jasmine.Suite.prototype.specComplete = function(specResult) {
|
||||
specResult.fullName = this.getFullName() + ' ' + specResult.description + '.';
|
||||
specResult.suite = this;
|
||||
this.env.removeAllSpies();
|
||||
this.env.reporter.reportSpecResults(specResult);
|
||||
this.queue.incrementQueue();
|
||||
};
|
||||
|
||||
jasmine.Suite.prototype.specs = function() {
|
||||
return this.specs_;
|
||||
};
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
jasmine.WaitsBlock = function(env, timeout, spec) {
|
||||
this.timeout = timeout;
|
||||
jasmine.Block.call(this, env, null, spec);
|
||||
};
|
||||
|
||||
jasmine.util.inherit(jasmine.WaitsBlock, jasmine.Block);
|
||||
|
||||
jasmine.WaitsBlock.prototype.execute = function (onComplete) {
|
||||
if (jasmine.VERBOSE) {
|
||||
this.env.reporter.log('>> Jasmine waiting for ' + this.timeout + ' ms...');
|
||||
}
|
||||
this.env.setTimeout(function () {
|
||||
onComplete();
|
||||
}, this.timeout);
|
||||
};
|
||||
@@ -1,54 +0,0 @@
|
||||
/**
|
||||
* A block which waits for some condition to become true, with timeout.
|
||||
*
|
||||
* @constructor
|
||||
* @extends jasmine.Block
|
||||
* @param {jasmine.Env} env The Jasmine environment.
|
||||
* @param {Number} timeout The maximum time in milliseconds to wait for the condition to become true.
|
||||
* @param {Function} latchFunction A function which returns true when the desired condition has been met.
|
||||
* @param {String} message The message to display if the desired condition hasn't been met within the given time period.
|
||||
* @param {jasmine.Spec} spec The Jasmine spec.
|
||||
*/
|
||||
jasmine.WaitsForBlock = function(env, timeout, latchFunction, message, spec) {
|
||||
this.timeout = timeout || env.defaultTimeoutInterval;
|
||||
this.latchFunction = latchFunction;
|
||||
this.message = message;
|
||||
this.totalTimeSpentWaitingForLatch = 0;
|
||||
jasmine.Block.call(this, env, null, spec);
|
||||
};
|
||||
jasmine.util.inherit(jasmine.WaitsForBlock, jasmine.Block);
|
||||
|
||||
jasmine.WaitsForBlock.TIMEOUT_INCREMENT = 10;
|
||||
|
||||
jasmine.WaitsForBlock.prototype.execute = function(onComplete) {
|
||||
if (jasmine.VERBOSE) {
|
||||
this.env.reporter.log('>> Jasmine waiting for ' + (this.message || 'something to happen'));
|
||||
}
|
||||
var latchFunctionResult;
|
||||
try {
|
||||
latchFunctionResult = this.latchFunction.apply(this.spec);
|
||||
} catch (e) {
|
||||
this.spec.fail(e);
|
||||
onComplete();
|
||||
return;
|
||||
}
|
||||
|
||||
if (latchFunctionResult) {
|
||||
onComplete();
|
||||
} else if (this.totalTimeSpentWaitingForLatch >= this.timeout) {
|
||||
var message = 'timed out after ' + this.timeout + ' msec waiting for ' + (this.message || 'something to happen');
|
||||
this.spec.fail({
|
||||
name: 'timeout',
|
||||
message: message
|
||||
});
|
||||
|
||||
this.abort = true;
|
||||
onComplete();
|
||||
} else {
|
||||
this.totalTimeSpentWaitingForLatch += jasmine.WaitsForBlock.TIMEOUT_INCREMENT;
|
||||
var self = this;
|
||||
this.env.setTimeout(function() {
|
||||
self.execute(onComplete);
|
||||
}, jasmine.WaitsForBlock.TIMEOUT_INCREMENT);
|
||||
}
|
||||
};
|
||||
@@ -5,6 +5,9 @@
|
||||
* @namespace
|
||||
*/
|
||||
var jasmine = {};
|
||||
if (typeof window == "undefined" && typeof exports == "object") {
|
||||
exports.jasmine = jasmine
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
@@ -431,13 +434,3 @@ jasmine.createSpyObj = function(baseName, methodNames) {
|
||||
}
|
||||
return obj;
|
||||
};
|
||||
|
||||
/**
|
||||
* All parameters are pretty-printed and concatenated together, then written to the current spec's output.
|
||||
*
|
||||
* Be careful not to leave calls to <code>jasmine.log</code> in production code.
|
||||
*/
|
||||
jasmine.log = function() {
|
||||
var spec = jasmine.getEnv().currentSpec;
|
||||
spec.log.apply(spec, arguments);
|
||||
};
|
||||
|
||||
@@ -111,6 +111,7 @@ jasmine.Clock = {
|
||||
|
||||
useMock: function() {
|
||||
if (!jasmine.Clock.isInstalled()) {
|
||||
//TODO: this is using an interface that doesn't exist.
|
||||
var spec = jasmine.getEnv().currentSpec;
|
||||
spec.after(jasmine.Clock.uninstallMock);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user