Only clear resources if suite is not disabled

[#66789174]
This commit is contained in:
Christopher Amavisca and Greg Cobb
2014-03-05 14:00:57 -08:00
parent 752a36d3ff
commit b200952195
7 changed files with 363 additions and 139 deletions

View File

@@ -36,6 +36,7 @@ getJasmineRequireObj().core = function(jRequire) {
j$.util = jRequire.util(); j$.util = jRequire.util();
j$.Any = jRequire.Any(); j$.Any = jRequire.Any();
j$.CallTracker = jRequire.CallTracker(); j$.CallTracker = jRequire.CallTracker();
j$.MockDate = jRequire.MockDate();
j$.Clock = jRequire.Clock(); j$.Clock = jRequire.Clock();
j$.DelayedFunctionScheduler = jRequire.DelayedFunctionScheduler(); j$.DelayedFunctionScheduler = jRequire.DelayedFunctionScheduler();
j$.Env = jRequire.Env(j$); j$.Env = jRequire.Env(j$);
@@ -49,6 +50,7 @@ getJasmineRequireObj().core = function(jRequire) {
j$.QueueRunner = jRequire.QueueRunner(j$); j$.QueueRunner = jRequire.QueueRunner(j$);
j$.ReportDispatcher = jRequire.ReportDispatcher(); j$.ReportDispatcher = jRequire.ReportDispatcher();
j$.Spec = jRequire.Spec(j$); j$.Spec = jRequire.Spec(j$);
j$.SpyRegistry = jRequire.SpyRegistry(j$);
j$.SpyStrategy = jRequire.SpyStrategy(); j$.SpyStrategy = jRequire.SpyStrategy();
j$.Suite = jRequire.Suite(); j$.Suite = jRequire.Suite();
j$.Timer = jRequire.Timer(); j$.Timer = jRequire.Timer();
@@ -223,6 +225,21 @@ getJasmineRequireObj().util = function() {
return obj === void 0; return obj === void 0;
}; };
util.clone = function(obj) {
if (Object.prototype.toString.apply(obj) === '[object Array]') {
return obj.slice();
}
var cloned = {};
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
cloned[prop] = obj[prop];
}
}
return cloned;
};
return util; return util;
}; };
@@ -232,9 +249,10 @@ getJasmineRequireObj().Spec = function(j$) {
this.resultCallback = attrs.resultCallback || function() {}; this.resultCallback = attrs.resultCallback || function() {};
this.id = attrs.id; this.id = attrs.id;
this.description = attrs.description || ''; this.description = attrs.description || '';
this.fn = attrs.fn; this.queueableFn = attrs.queueableFn;
this.beforeFns = attrs.beforeFns || function() { return []; }; this.beforeFns = attrs.beforeFns || function() { return []; };
this.afterFns = attrs.afterFns || function() { return []; }; this.afterFns = attrs.afterFns || function() { return []; };
this.userContext = attrs.userContext || function() { return {}; };
this.onStart = attrs.onStart || function() {}; this.onStart = attrs.onStart || function() {};
this.exceptionFormatter = attrs.exceptionFormatter || function() {}; this.exceptionFormatter = attrs.exceptionFormatter || function() {};
this.getSpecName = attrs.getSpecName || function() { return ''; }; this.getSpecName = attrs.getSpecName || function() { return ''; };
@@ -242,7 +260,7 @@ getJasmineRequireObj().Spec = function(j$) {
this.queueRunnerFactory = attrs.queueRunnerFactory || function() {}; this.queueRunnerFactory = attrs.queueRunnerFactory || function() {};
this.catchingExceptions = attrs.catchingExceptions || function() { return true; }; this.catchingExceptions = attrs.catchingExceptions || function() { return true; };
if (!this.fn) { if (!this.queueableFn.fn) {
this.pend(); this.pend();
} }
@@ -275,30 +293,15 @@ getJasmineRequireObj().Spec = function(j$) {
return; return;
} }
var allFns = this.beforeFns().concat(this.fn).concat(this.afterFns()); var allFns = this.beforeFns().concat(this.queueableFn).concat(this.afterFns());
this.queueRunnerFactory({ this.queueRunnerFactory({
fns: allFns, queueableFns: allFns,
onException: onException, onException: function() { self.onException.apply(self, arguments); },
onComplete: complete, onComplete: complete,
enforceTimeout: function() { return true; } userContext: this.userContext()
}); });
function onException(e) {
if (Spec.isPendingSpecException(e)) {
self.pend();
return;
}
self.addExpectationResult(false, {
matcherName: '',
passed: false,
expected: '',
actual: '',
error: e
});
}
function complete() { function complete() {
self.result.status = self.status(); self.result.status = self.status();
self.resultCallback(self.result); self.resultCallback(self.result);
@@ -309,6 +312,21 @@ getJasmineRequireObj().Spec = function(j$) {
} }
}; };
Spec.prototype.onException = function onException(e) {
if (Spec.isPendingSpecException(e)) {
this.pend();
return;
}
this.addExpectationResult(false, {
matcherName: '',
passed: false,
expected: '',
actual: '',
error: e
});
};
Spec.prototype.disable = function() { Spec.prototype.disable = function() {
this.disabled = true; this.disabled = true;
}; };
@@ -333,6 +351,10 @@ getJasmineRequireObj().Spec = function(j$) {
} }
}; };
Spec.prototype.isExecutable = function() {
return !this.disabled && !this.markedPending;
};
Spec.prototype.getFullName = function() { Spec.prototype.getFullName = function() {
return this.getSpecName(this); return this.getSpecName(this);
}; };
@@ -363,14 +385,22 @@ getJasmineRequireObj().Env = function(j$) {
var realSetTimeout = j$.getGlobal().setTimeout; var realSetTimeout = j$.getGlobal().setTimeout;
var realClearTimeout = j$.getGlobal().clearTimeout; var realClearTimeout = j$.getGlobal().clearTimeout;
this.clock = new j$.Clock(global, new j$.DelayedFunctionScheduler()); this.clock = new j$.Clock(global, new j$.DelayedFunctionScheduler(), new j$.MockDate(global));
var runnableLookupTable = {}; var runnableLookupTable = {};
var runnableResources = {};
var spies = [];
var currentSpec = null; var currentSpec = null;
var currentSuite = null; var currentlyExecutingSuites = [];
var currentDeclarationSuite = null;
var currentSuite = function() {
return currentlyExecutingSuites[currentlyExecutingSuites.length - 1];
};
var currentRunnable = function() {
return currentSpec || currentSuite();
};
var reporter = new j$.ReportDispatcher([ var reporter = new j$.ReportDispatcher([
'jasmineStarted', 'jasmineStarted',
@@ -385,11 +415,15 @@ getJasmineRequireObj().Env = function(j$) {
return true; return true;
}; };
var equalityTesters = [];
var customEqualityTesters = [];
this.addCustomEqualityTester = function(tester) { this.addCustomEqualityTester = function(tester) {
customEqualityTesters.push(tester); runnableResources[currentRunnable().id].customEqualityTesters.push(tester);
};
this.addMatchers = function(matchersToAdd) {
var customMatchers = runnableResources[currentRunnable().id].customMatchers;
for (var matcherName in matchersToAdd) {
customMatchers[matcherName] = matchersToAdd[matcherName];
}
}; };
j$.Expectation.addCoreMatchers(j$.matchers); j$.Expectation.addCoreMatchers(j$.matchers);
@@ -407,7 +441,8 @@ getJasmineRequireObj().Env = function(j$) {
var expectationFactory = function(actual, spec) { var expectationFactory = function(actual, spec) {
return j$.Expectation.Factory({ return j$.Expectation.Factory({
util: j$.matchersUtil, util: j$.matchersUtil,
customEqualityTesters: customEqualityTesters, customEqualityTesters: runnableResources[spec.id].customEqualityTesters,
customMatchers: runnableResources[spec.id].customMatchers,
actual: actual, actual: actual,
addExpectationResult: addExpectationResult addExpectationResult: addExpectationResult
}); });
@@ -417,9 +452,20 @@ getJasmineRequireObj().Env = function(j$) {
} }
}; };
var specStarted = function(spec) { var defaultResourcesForRunnable = function(id, parentRunnableId) {
currentSpec = spec; var resources = {spies: [], customEqualityTesters: [], customMatchers: {}};
reporter.specStarted(spec.result);
if(runnableResources[parentRunnableId]){
resources.customEqualityTesters = j$.util.clone(runnableResources[parentRunnableId].customEqualityTesters);
resources.customMatchers = j$.util.clone(runnableResources[parentRunnableId].customMatchers);
}
runnableResources[id] = resources;
};
var clearResourcesForRunnable = function(id) {
spyRegistry.clearSpies();
delete runnableResources[id];
}; };
var beforeFns = function(suite) { var beforeFns = function(suite) {
@@ -501,7 +547,8 @@ getJasmineRequireObj().Env = function(j$) {
resultCallback: function() {} // TODO - hook this up resultCallback: function() {} // TODO - hook this up
}); });
runnableLookupTable[topSuite.id] = topSuite; runnableLookupTable[topSuite.id] = topSuite;
currentSuite = topSuite; defaultResourcesForRunnable(topSuite.id);
currentDeclarationSuite = topSuite;
this.topSuite = function() { this.topSuite = function() {
return topSuite; return topSuite;
@@ -513,50 +560,26 @@ getJasmineRequireObj().Env = function(j$) {
var allFns = []; var allFns = [];
for(var i = 0; i < runnablesToRun.length; i++) { for(var i = 0; i < runnablesToRun.length; i++) {
var runnable = runnableLookupTable[runnablesToRun[i]]; var runnable = runnableLookupTable[runnablesToRun[i]];
allFns.push((function(runnable) { return function(done) { runnable.execute(done); }; })(runnable)); allFns.push((function(runnable) { return { fn: function(done) { runnable.execute(done); } }; })(runnable));
} }
reporter.jasmineStarted({ reporter.jasmineStarted({
totalSpecsDefined: totalSpecsDefined totalSpecsDefined: totalSpecsDefined
}); });
queueRunnerFactory({fns: allFns, onComplete: reporter.jasmineDone}); queueRunnerFactory({queueableFns: allFns, onComplete: reporter.jasmineDone});
}; };
this.addReporter = function(reporterToAdd) { this.addReporter = function(reporterToAdd) {
reporter.addReporter(reporterToAdd); reporter.addReporter(reporterToAdd);
}; };
this.addMatchers = function(matchersToAdd) { var spyRegistry = new j$.SpyRegistry({currentSpies: function() {
j$.Expectation.addMatchers(matchersToAdd); return runnableResources[currentRunnable().id].spies;
}; }});
this.spyOn = function(obj, methodName) { this.spyOn = function() {
if (j$.util.isUndefined(obj)) { return spyRegistry.spyOn.apply(spyRegistry, arguments);
throw new Error('spyOn could not find an object to spy upon for ' + methodName + '()');
}
if (j$.util.isUndefined(obj[methodName])) {
throw new Error(methodName + '() method does not exist');
}
if (obj[methodName] && j$.isSpy(obj[methodName])) {
//TODO?: should this return the current spy? Downside: may cause user confusion about spy state
throw new Error(methodName + ' has already been spied upon');
}
var spy = j$.createSpy(methodName, obj[methodName]);
spies.push({
spy: spy,
baseObj: obj,
methodName: methodName,
originalValue: obj[methodName]
});
obj[methodName] = spy;
return spy;
}; };
var suiteFactory = function(description) { var suiteFactory = function(description) {
@@ -564,24 +587,34 @@ getJasmineRequireObj().Env = function(j$) {
env: self, env: self,
id: getNextSuiteId(), id: getNextSuiteId(),
description: description, description: description,
parentSuite: currentSuite, parentSuite: currentDeclarationSuite,
queueRunner: queueRunnerFactory, queueRunner: queueRunnerFactory,
onStart: suiteStarted, onStart: suiteStarted,
resultCallback: function(attrs) { resultCallback: function(attrs) {
if (!suite.disabled) {
clearResourcesForRunnable(suite.id);
currentlyExecutingSuites.pop();
}
reporter.suiteDone(attrs); reporter.suiteDone(attrs);
} }
}); });
runnableLookupTable[suite.id] = suite; runnableLookupTable[suite.id] = suite;
return suite; return suite;
function suiteStarted(suite) {
currentlyExecutingSuites.push(suite);
defaultResourcesForRunnable(suite.id, suite.parentSuite.id);
reporter.suiteStarted(suite.result);
}
}; };
this.describe = function(description, specDefinitions) { this.describe = function(description, specDefinitions) {
var suite = suiteFactory(description); var suite = suiteFactory(description);
var parentSuite = currentSuite; var parentSuite = currentDeclarationSuite;
parentSuite.addChild(suite); parentSuite.addChild(suite);
currentSuite = suite; currentDeclarationSuite = suite;
var declarationError = null; var declarationError = null;
try { try {
@@ -596,7 +629,7 @@ getJasmineRequireObj().Env = function(j$) {
}); });
} }
currentSuite = parentSuite; currentDeclarationSuite = parentSuite;
return suite; return suite;
}; };
@@ -624,7 +657,8 @@ getJasmineRequireObj().Env = function(j$) {
description: description, description: description,
expectationResultFactory: expectationResultFactory, expectationResultFactory: expectationResultFactory,
queueRunnerFactory: queueRunnerFactory, queueRunnerFactory: queueRunnerFactory,
fn: fn userContext: function() { return suite.clonedSharedUserContext(); },
queueableFn: { fn: fn, timeout: function() { return j$.DEFAULT_TIMEOUT_INTERVAL; } }
}); });
runnableLookupTable[spec.id] = spec; runnableLookupTable[spec.id] = spec;
@@ -635,30 +669,22 @@ getJasmineRequireObj().Env = function(j$) {
return spec; return spec;
function removeAllSpies() {
for (var i = 0; i < spies.length; i++) {
var spyEntry = spies[i];
spyEntry.baseObj[spyEntry.methodName] = spyEntry.originalValue;
}
spies = [];
}
function specResultCallback(result) { function specResultCallback(result) {
removeAllSpies(); clearResourcesForRunnable(spec.id);
j$.Expectation.resetMatchers();
customEqualityTesters = [];
currentSpec = null; currentSpec = null;
reporter.specDone(result); reporter.specDone(result);
} }
};
var suiteStarted = function(suite) { function specStarted(spec) {
reporter.suiteStarted(suite.result); currentSpec = spec;
defaultResourcesForRunnable(spec.id, suite.id);
reporter.specStarted(spec.result);
}
}; };
this.it = function(description, fn) { this.it = function(description, fn) {
var spec = specFactory(description, fn, currentSuite); var spec = specFactory(description, fn, currentDeclarationSuite);
currentSuite.addChild(spec); currentDeclarationSuite.addChild(spec);
return spec; return spec;
}; };
@@ -673,11 +699,19 @@ getJasmineRequireObj().Env = function(j$) {
}; };
this.beforeEach = function(beforeEachFunction) { this.beforeEach = function(beforeEachFunction) {
currentSuite.beforeEach(beforeEachFunction); currentDeclarationSuite.beforeEach({ fn: beforeEachFunction, timeout: function() { return j$.DEFAULT_TIMEOUT_INTERVAL; } });
};
this.beforeAll = function(beforeAllFunction) {
currentDeclarationSuite.beforeAll({ fn: beforeAllFunction, timeout: function() { return j$.DEFAULT_TIMEOUT_INTERVAL; } });
}; };
this.afterEach = function(afterEachFunction) { this.afterEach = function(afterEachFunction) {
currentSuite.afterEach(afterEachFunction); currentDeclarationSuite.afterEach({ fn: afterEachFunction, timeout: function() { return j$.DEFAULT_TIMEOUT_INTERVAL; } });
};
this.afterAll = function(afterAllFunction) {
currentDeclarationSuite.afterAll({ fn: afterAllFunction, timeout: function() { return j$.DEFAULT_TIMEOUT_INTERVAL; } });
}; };
this.pending = function() { this.pending = function() {
@@ -851,7 +885,7 @@ getJasmineRequireObj().CallTracker = function() {
}; };
getJasmineRequireObj().Clock = function() { getJasmineRequireObj().Clock = function() {
function Clock(global, delayedFunctionScheduler) { function Clock(global, delayedFunctionScheduler, mockDate) {
var self = this, var self = this,
realTimingFunctions = { realTimingFunctions = {
setTimeout: global.setTimeout, setTimeout: global.setTimeout,
@@ -868,19 +902,28 @@ getJasmineRequireObj().Clock = function() {
installed = false, installed = false,
timer; timer;
self.install = function() { self.install = function() {
replace(global, fakeTimingFunctions); replace(global, fakeTimingFunctions);
timer = fakeTimingFunctions; timer = fakeTimingFunctions;
installed = true; installed = true;
return self;
}; };
self.uninstall = function() { self.uninstall = function() {
delayedFunctionScheduler.reset(); delayedFunctionScheduler.reset();
mockDate.uninstall();
replace(global, realTimingFunctions); replace(global, realTimingFunctions);
timer = realTimingFunctions; timer = realTimingFunctions;
installed = false; installed = false;
}; };
self.mockDate = function(initialDate) {
mockDate.install(initialDate);
};
self.setTimeout = function(fn, delay, params) { self.setTimeout = function(fn, delay, params) {
if (legacyIE()) { if (legacyIE()) {
if (arguments.length > 2) { if (arguments.length > 2) {
@@ -911,6 +954,7 @@ getJasmineRequireObj().Clock = function() {
self.tick = function(millis) { self.tick = function(millis) {
if (installed) { if (installed) {
mockDate.tick(millis);
delayedFunctionScheduler.tick(millis); delayedFunctionScheduler.tick(millis);
} else { } else {
throw new Error('Mock clock is not installed, use jasmine.clock().install()'); throw new Error('Mock clock is not installed, use jasmine.clock().install()');
@@ -1132,8 +1176,6 @@ getJasmineRequireObj().ExceptionFormatter = function() {
getJasmineRequireObj().Expectation = function() { getJasmineRequireObj().Expectation = function() {
var matchers = {};
function Expectation(options) { function Expectation(options) {
this.util = options.util || { buildFailureMessage: function() {} }; this.util = options.util || { buildFailureMessage: function() {} };
this.customEqualityTesters = options.customEqualityTesters || []; this.customEqualityTesters = options.customEqualityTesters || [];
@@ -1141,8 +1183,9 @@ getJasmineRequireObj().Expectation = function() {
this.addExpectationResult = options.addExpectationResult || function(){}; this.addExpectationResult = options.addExpectationResult || function(){};
this.isNot = options.isNot; this.isNot = options.isNot;
for (var matcherName in matchers) { var customMatchers = options.customMatchers || {};
this[matcherName] = matchers[matcherName]; for (var matcherName in customMatchers) {
this[matcherName] = Expectation.prototype.wrapCompare(matcherName, customMatchers[matcherName]);
} }
} }
@@ -1209,19 +1252,6 @@ getJasmineRequireObj().Expectation = function() {
} }
}; };
Expectation.addMatchers = function(matchersToAdd) {
for (var name in matchersToAdd) {
var matcher = matchersToAdd[name];
matchers[name] = Expectation.prototype.wrapCompare(name, matcher);
}
};
Expectation.resetMatchers = function() {
for (var name in matchers) {
delete matchers[name];
}
};
Expectation.Factory = function(options) { Expectation.Factory = function(options) {
options = options || {}; options = options || {};
@@ -1284,6 +1314,73 @@ getJasmineRequireObj().buildExpectationResult = function() {
return buildExpectationResult; return buildExpectationResult;
}; };
getJasmineRequireObj().MockDate = function() {
function MockDate(global) {
var self = this;
var currentTime = 0;
if (!global || !global.Date) {
self.install = function() {};
self.tick = function() {};
self.uninstall = function() {};
return self;
}
var GlobalDate = global.Date;
self.install = function(mockDate) {
if (mockDate instanceof GlobalDate) {
currentTime = mockDate.getTime();
} else {
currentTime = new GlobalDate().getTime();
}
global.Date = FakeDate;
};
self.tick = function(millis) {
millis = millis || 0;
currentTime = currentTime + millis;
};
self.uninstall = function() {
currentTime = 0;
global.Date = GlobalDate;
};
createDateProperties();
return self;
function FakeDate() {
if (arguments.length === 0) {
return new GlobalDate(currentTime);
} else {
return new GlobalDate(arguments[0], arguments[1], arguments[2],
arguments[3], arguments[4], arguments[5], arguments[6]);
}
}
function createDateProperties() {
FakeDate.now = function() {
if (GlobalDate.now) {
return currentTime;
} else {
throw new Error('Browser does not support Date.now()');
}
};
FakeDate.toSource = GlobalDate.toSource;
FakeDate.toString = GlobalDate.toString;
FakeDate.parse = GlobalDate.parse;
FakeDate.UTC = GlobalDate.UTC;
}
}
return MockDate;
};
getJasmineRequireObj().ObjectContaining = function(j$) { getJasmineRequireObj().ObjectContaining = function(j$) {
function ObjectContaining(sample) { function ObjectContaining(sample) {
@@ -1467,31 +1564,30 @@ getJasmineRequireObj().QueueRunner = function(j$) {
} }
function QueueRunner(attrs) { function QueueRunner(attrs) {
this.fns = attrs.fns || []; this.queueableFns = attrs.queueableFns || [];
this.onComplete = attrs.onComplete || function() {}; this.onComplete = attrs.onComplete || function() {};
this.clearStack = attrs.clearStack || function(fn) {fn();}; this.clearStack = attrs.clearStack || function(fn) {fn();};
this.onException = attrs.onException || function() {}; this.onException = attrs.onException || function() {};
this.catchException = attrs.catchException || function() { return true; }; this.catchException = attrs.catchException || function() { return true; };
this.enforceTimeout = attrs.enforceTimeout || function() { return false; }; this.userContext = attrs.userContext || {};
this.userContext = {};
this.timer = attrs.timeout || {setTimeout: setTimeout, clearTimeout: clearTimeout}; this.timer = attrs.timeout || {setTimeout: setTimeout, clearTimeout: clearTimeout};
} }
QueueRunner.prototype.execute = function() { QueueRunner.prototype.execute = function() {
this.run(this.fns, 0); this.run(this.queueableFns, 0);
}; };
QueueRunner.prototype.run = function(fns, recursiveIndex) { QueueRunner.prototype.run = function(queueableFns, recursiveIndex) {
var length = fns.length, var length = queueableFns.length,
self = this, self = this,
iterativeIndex; iterativeIndex;
for(iterativeIndex = recursiveIndex; iterativeIndex < length; iterativeIndex++) { for(iterativeIndex = recursiveIndex; iterativeIndex < length; iterativeIndex++) {
var fn = fns[iterativeIndex]; var queueableFn = queueableFns[iterativeIndex];
if (fn.length > 0) { if (queueableFn.fn.length > 0) {
return attemptAsync(fn); return attemptAsync(queueableFn);
} else { } else {
attemptSync(fn); attemptSync(queueableFn);
} }
} }
@@ -1501,33 +1597,33 @@ getJasmineRequireObj().QueueRunner = function(j$) {
this.clearStack(this.onComplete); this.clearStack(this.onComplete);
} }
function attemptSync(fn) { function attemptSync(queueableFn) {
try { try {
fn.call(self.userContext); queueableFn.fn.call(self.userContext);
} catch (e) { } catch (e) {
handleException(e); handleException(e);
} }
} }
function attemptAsync(fn) { function attemptAsync(queueableFn) {
var clearTimeout = function () { var clearTimeout = function () {
Function.prototype.apply.apply(self.timer.clearTimeout, [j$.getGlobal(), [timeoutId]]); Function.prototype.apply.apply(self.timer.clearTimeout, [j$.getGlobal(), [timeoutId]]);
}, },
next = once(function () { next = once(function () {
clearTimeout(timeoutId); clearTimeout(timeoutId);
self.run(fns, iterativeIndex + 1); self.run(queueableFns, iterativeIndex + 1);
}), }),
timeoutId; timeoutId;
if (self.enforceTimeout()) { if (queueableFn.timeout) {
timeoutId = Function.prototype.apply.apply(self.timer.setTimeout, [j$.getGlobal(), [function() { timeoutId = Function.prototype.apply.apply(self.timer.setTimeout, [j$.getGlobal(), [function() {
self.onException(new Error('Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.')); self.onException(new Error('Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.'));
next(); next();
}, j$.DEFAULT_TIMEOUT_INTERVAL]]); }, queueableFn.timeout()]]);
} }
try { try {
fn.call(self.userContext, next); queueableFn.fn.call(self.userContext, next);
} catch (e) { } catch (e) {
handleException(e); handleException(e);
next(); next();
@@ -1583,6 +1679,52 @@ getJasmineRequireObj().ReportDispatcher = function() {
}; };
getJasmineRequireObj().SpyRegistry = function(j$) {
function SpyRegistry(options) {
options = options || {};
var currentSpies = options.currentSpies || function() { return []; };
this.spyOn = function(obj, methodName) {
if (j$.util.isUndefined(obj)) {
throw new Error('spyOn could not find an object to spy upon for ' + methodName + '()');
}
if (j$.util.isUndefined(obj[methodName])) {
throw new Error(methodName + '() method does not exist');
}
if (obj[methodName] && j$.isSpy(obj[methodName])) {
//TODO?: should this return the current spy? Downside: may cause user confusion about spy state
throw new Error(methodName + ' has already been spied upon');
}
var spy = j$.createSpy(methodName, obj[methodName]);
currentSpies().push({
spy: spy,
baseObj: obj,
methodName: methodName,
originalValue: obj[methodName]
});
obj[methodName] = spy;
return spy;
};
this.clearSpies = function() {
var spies = currentSpies();
for (var i = 0; i < spies.length; i++) {
var spyEntry = spies[i];
spyEntry.baseObj[spyEntry.methodName] = spyEntry.originalValue;
}
};
}
return SpyRegistry;
};
getJasmineRequireObj().SpyStrategy = function() { getJasmineRequireObj().SpyStrategy = function() {
function SpyStrategy(options) { function SpyStrategy(options) {
@@ -1647,6 +1789,8 @@ getJasmineRequireObj().Suite = function() {
this.beforeFns = []; this.beforeFns = [];
this.afterFns = []; this.afterFns = [];
this.beforeAllFns = [];
this.afterAllFns = [];
this.queueRunner = attrs.queueRunner || function() {}; this.queueRunner = attrs.queueRunner || function() {};
this.disabled = false; this.disabled = false;
@@ -1678,10 +1822,18 @@ getJasmineRequireObj().Suite = function() {
this.beforeFns.unshift(fn); this.beforeFns.unshift(fn);
}; };
Suite.prototype.beforeAll = function(fn) {
this.beforeAllFns.push(fn);
};
Suite.prototype.afterEach = function(fn) { Suite.prototype.afterEach = function(fn) {
this.afterFns.unshift(fn); this.afterFns.unshift(fn);
}; };
Suite.prototype.afterAll = function(fn) {
this.afterAllFns.push(fn);
};
Suite.prototype.addChild = function(child) { Suite.prototype.addChild = function(child) {
this.children.push(child); this.children.push(child);
}; };
@@ -1695,15 +1847,23 @@ getJasmineRequireObj().Suite = function() {
var allFns = []; var allFns = [];
for (var i = 0; i < this.children.length; i++) { if (this.isExecutable()) {
allFns.push(wrapChildAsAsync(this.children[i])); allFns = this.beforeAllFns;
for (var i = 0; i < this.children.length; i++) {
allFns.push(wrapChildAsAsync(this.children[i]));
}
allFns = allFns.concat(this.afterAllFns);
} }
this.onStart(this); this.onStart(this);
this.queueRunner({ this.queueRunner({
fns: allFns, queueableFns: allFns,
onComplete: complete onComplete: complete,
userContext: this.sharedUserContext(),
onException: function() { self.onException.apply(self, arguments); }
}); });
function complete() { function complete() {
@@ -1715,10 +1875,51 @@ getJasmineRequireObj().Suite = function() {
} }
function wrapChildAsAsync(child) { function wrapChildAsAsync(child) {
return function(done) { child.execute(done); }; return { fn: function(done) { child.execute(done); } };
} }
}; };
Suite.prototype.isExecutable = function() {
var foundActive = false;
for(var i = 0; i < this.children.length; i++) {
if(this.children[i].isExecutable()) {
foundActive = true;
break;
}
}
return foundActive;
};
Suite.prototype.sharedUserContext = function() {
if (!this.sharedContext) {
this.sharedContext = this.parentSuite ? clone(this.parentSuite.sharedUserContext()) : {};
}
return this.sharedContext;
};
Suite.prototype.clonedSharedUserContext = function() {
return clone(this.sharedUserContext());
};
Suite.prototype.onException = function() {
for (var i = 0; i < this.children.length; i++) {
var child = this.children[i];
child.onException.apply(child, arguments);
}
};
function clone(obj) {
var clonedObj = {};
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
clonedObj[prop] = obj[prop];
}
}
return clonedObj;
}
return Suite; return Suite;
}; };

View File

@@ -80,7 +80,7 @@ describe("Env integration", function() {
env.describe("Outer suite", function() { env.describe("Outer suite", function() {
env.it("an outer spec", function() { env.it("an outer spec", function() {
calls.push('an outer spec') calls.push('an outer spec');
}); });
env.describe("Inner suite", function() { env.describe("Inner suite", function() {
env.it("an inner spec", function() { env.it("an inner spec", function() {
@@ -803,4 +803,3 @@ describe("Env integration", function() {
env.execute(); env.execute();
}); });
}); });

View File

@@ -244,6 +244,29 @@ describe("jasmine spec running", function () {
env.addReporter({jasmineDone: assertions}); env.addReporter({jasmineDone: assertions});
env.execute(); env.execute();
});
it("should allow top level suites to be disabled", function() {
var specInADisabledSuite = jasmine.createSpy("specInADisabledSuite"),
otherSpec = jasmine.createSpy("otherSpec");
env.xdescribe('A disabled suite', function() {
env.it('spec inside a disabled suite', specInADisabledSuite);
});
env.describe('Another suite', function() {
env.it('another spec', otherSpec);
});
var assertions = function() {
expect(specInADisabledSuite).not.toHaveBeenCalled();
expect(otherSpec).toHaveBeenCalled();
done();
};
env.addReporter({jasmineDone: assertions});
env.execute();
});
it("should set all pending specs to pending when a suite is run", function(done) { it("should set all pending specs to pending when a suite is run", function(done) {
var pendingSpec, var pendingSpec,

View File

@@ -22,11 +22,11 @@ getJasmineRequireObj().Env = function(j$) {
var currentSuite = function() { var currentSuite = function() {
return currentlyExecutingSuites[currentlyExecutingSuites.length - 1]; return currentlyExecutingSuites[currentlyExecutingSuites.length - 1];
} };
var currentRunnable = function() { var currentRunnable = function() {
return currentSpec || currentSuite(); return currentSpec || currentSuite();
} };
var reporter = new j$.ReportDispatcher([ var reporter = new j$.ReportDispatcher([
'jasmineStarted', 'jasmineStarted',
@@ -217,8 +217,10 @@ getJasmineRequireObj().Env = function(j$) {
queueRunner: queueRunnerFactory, queueRunner: queueRunnerFactory,
onStart: suiteStarted, onStart: suiteStarted,
resultCallback: function(attrs) { resultCallback: function(attrs) {
clearResourcesForRunnable(suite.id); if (!suite.disabled) {
currentlyExecutingSuites.pop(); clearResourcesForRunnable(suite.id);
currentlyExecutingSuites.pop();
}
reporter.suiteDone(attrs); reporter.suiteDone(attrs);
} }
}); });

View File

@@ -51,7 +51,7 @@ getJasmineRequireObj().MockDate = function() {
if (GlobalDate.now) { if (GlobalDate.now) {
return currentTime; return currentTime;
} else { } else {
throw new Error("Browser does not support Date.now()"); throw new Error('Browser does not support Date.now()');
} }
}; };

View File

@@ -1,7 +1,7 @@
getJasmineRequireObj().SpyRegistry = function(j$) { getJasmineRequireObj().SpyRegistry = function(j$) {
function SpyRegistry(options) { function SpyRegistry(options) {
var options = options || {}; options = options || {};
var currentSpies = options.currentSpies || function() { return []; }; var currentSpies = options.currentSpies || function() { return []; };
this.spyOn = function(obj, methodName) { this.spyOn = function(obj, methodName) {
@@ -43,4 +43,3 @@ getJasmineRequireObj().SpyRegistry = function(j$) {
return SpyRegistry; return SpyRegistry;
}; };

View File

@@ -31,7 +31,7 @@ getJasmineRequireObj().util = function() {
}; };
util.clone = function(obj) { util.clone = function(obj) {
if (Object.prototype.toString.apply(obj) === "[object Array]") { if (Object.prototype.toString.apply(obj) === '[object Array]') {
return obj.slice(); return obj.slice();
} }
@@ -43,7 +43,7 @@ getJasmineRequireObj().util = function() {
} }
return cloned; return cloned;
} };
return util; return util;
}; };