Extracted suite building out of Env
This commit is contained in:
@@ -100,6 +100,7 @@ var getJasmineRequireObj = (function(jasmineGlobal) {
|
|||||||
j$.StringContaining = jRequire.StringContaining(j$);
|
j$.StringContaining = jRequire.StringContaining(j$);
|
||||||
j$.UserContext = jRequire.UserContext(j$);
|
j$.UserContext = jRequire.UserContext(j$);
|
||||||
j$.Suite = jRequire.Suite(j$);
|
j$.Suite = jRequire.Suite(j$);
|
||||||
|
j$.SuiteBuilder = jRequire.SuiteBuilder(j$);
|
||||||
j$.Timer = jRequire.Timer();
|
j$.Timer = jRequire.Timer();
|
||||||
j$.TreeProcessor = jRequire.TreeProcessor();
|
j$.TreeProcessor = jRequire.TreeProcessor();
|
||||||
j$.version = jRequire.version();
|
j$.version = jRequire.version();
|
||||||
@@ -1100,8 +1101,6 @@ getJasmineRequireObj().Env = function(j$) {
|
|||||||
const self = this;
|
const self = this;
|
||||||
const global = options.global || j$.getGlobal();
|
const global = options.global || j$.getGlobal();
|
||||||
|
|
||||||
let totalSpecsDefined = 0;
|
|
||||||
|
|
||||||
const realSetTimeout = global.setTimeout;
|
const realSetTimeout = global.setTimeout;
|
||||||
const realClearTimeout = global.clearTimeout;
|
const realClearTimeout = global.clearTimeout;
|
||||||
const clearStack = j$.getClearStack(global);
|
const clearStack = j$.getClearStack(global);
|
||||||
@@ -1118,14 +1117,11 @@ getJasmineRequireObj().Env = function(j$) {
|
|||||||
return r ? r.id : null;
|
return r ? r.id : null;
|
||||||
});
|
});
|
||||||
|
|
||||||
let topSuite;
|
|
||||||
let currentSpec = null;
|
let currentSpec = null;
|
||||||
const currentlyExecutingSuites = [];
|
const currentlyExecutingSuites = [];
|
||||||
const focusedRunables = [];
|
|
||||||
let currentDeclarationSuite = null;
|
|
||||||
let hasFailures = false;
|
let hasFailures = false;
|
||||||
let deprecator;
|
|
||||||
let reporter;
|
let reporter;
|
||||||
|
let topSuite;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This represents the available options to configure Jasmine.
|
* This represents the available options to configure Jasmine.
|
||||||
@@ -1345,18 +1341,6 @@ getJasmineRequireObj().Env = function(j$) {
|
|||||||
j$.Expectation.addCoreMatchers(j$.matchers);
|
j$.Expectation.addCoreMatchers(j$.matchers);
|
||||||
j$.Expectation.addAsyncCoreMatchers(j$.asyncMatchers);
|
j$.Expectation.addAsyncCoreMatchers(j$.asyncMatchers);
|
||||||
|
|
||||||
let nextSpecId = 0;
|
|
||||||
|
|
||||||
function getNextSpecId() {
|
|
||||||
return 'spec' + nextSpecId++;
|
|
||||||
}
|
|
||||||
|
|
||||||
let nextSuiteId = 0;
|
|
||||||
|
|
||||||
function getNextSuiteId() {
|
|
||||||
return 'suite' + nextSuiteId++;
|
|
||||||
}
|
|
||||||
|
|
||||||
const expectationFactory = function(actual, spec) {
|
const expectationFactory = function(actual, spec) {
|
||||||
return j$.Expectation.factory({
|
return j$.Expectation.factory({
|
||||||
matchersUtil: runableResources.makeMatchersUtil(),
|
matchersUtil: runableResources.makeMatchersUtil(),
|
||||||
@@ -1450,43 +1434,6 @@ getJasmineRequireObj().Env = function(j$) {
|
|||||||
return spec.addExpectationResult(passed, result);
|
return spec.addExpectationResult(passed, result);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const suiteAsyncExpectationFactory = function(actual, suite) {
|
|
||||||
return asyncExpectationFactory(actual, suite, 'Suite');
|
|
||||||
};
|
|
||||||
|
|
||||||
const specAsyncExpectationFactory = function(actual, suite) {
|
|
||||||
return asyncExpectationFactory(actual, suite, 'Spec');
|
|
||||||
};
|
|
||||||
|
|
||||||
function beforeAndAfterFns(targetSuite) {
|
|
||||||
return function() {
|
|
||||||
let befores = [],
|
|
||||||
afters = [],
|
|
||||||
suite = targetSuite;
|
|
||||||
|
|
||||||
while (suite) {
|
|
||||||
befores = befores.concat(suite.beforeFns);
|
|
||||||
afters = afters.concat(suite.afterFns);
|
|
||||||
|
|
||||||
suite = suite.parentSuite;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
befores: befores.reverse(),
|
|
||||||
afters: afters
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function getSpecName(spec, suite) {
|
|
||||||
const fullName = [spec.description],
|
|
||||||
suiteFullName = suite.getFullName();
|
|
||||||
|
|
||||||
if (suiteFullName !== '') {
|
|
||||||
fullName.unshift(suiteFullName);
|
|
||||||
}
|
|
||||||
return fullName.join(' ');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Causes a deprecation warning to be logged to the console and reported to
|
* Causes a deprecation warning to be logged to the console and reported to
|
||||||
@@ -1548,16 +1495,17 @@ getJasmineRequireObj().Env = function(j$) {
|
|||||||
new j$.QueueRunner(options).execute(args);
|
new j$.QueueRunner(options).execute(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
topSuite = new j$.Suite({
|
const suiteBuilder = new j$.SuiteBuilder({
|
||||||
id: getNextSuiteId(),
|
env: this,
|
||||||
description: 'Jasmine__TopLevel__Suite',
|
expectationFactory,
|
||||||
expectationFactory: expectationFactory,
|
asyncExpectationFactory,
|
||||||
asyncExpectationFactory: suiteAsyncExpectationFactory,
|
onLateError: recordLateError,
|
||||||
autoCleanClosures: config.autoCleanClosures,
|
specResultCallback,
|
||||||
onLateError: recordLateError
|
specStarted,
|
||||||
|
queueRunnerFactory
|
||||||
});
|
});
|
||||||
deprecator = new j$.Deprecator(topSuite);
|
topSuite = suiteBuilder.topSuite;
|
||||||
currentDeclarationSuite = topSuite;
|
const deprecator = new j$.Deprecator(topSuite);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides the root suite, through which all suites and specs can be
|
* Provides the root suite, through which all suites and specs can be
|
||||||
@@ -1687,8 +1635,8 @@ getJasmineRequireObj().Env = function(j$) {
|
|||||||
installGlobalErrors();
|
installGlobalErrors();
|
||||||
|
|
||||||
if (!runablesToRun) {
|
if (!runablesToRun) {
|
||||||
if (focusedRunables.length) {
|
if (suiteBuilder.focusedRunables.length) {
|
||||||
runablesToRun = focusedRunables;
|
runablesToRun = suiteBuilder.focusedRunables;
|
||||||
} else {
|
} else {
|
||||||
runablesToRun = [topSuite.id];
|
runablesToRun = [topSuite.id];
|
||||||
}
|
}
|
||||||
@@ -1768,7 +1716,7 @@ getJasmineRequireObj().Env = function(j$) {
|
|||||||
*/
|
*/
|
||||||
reporter.jasmineStarted(
|
reporter.jasmineStarted(
|
||||||
{
|
{
|
||||||
totalSpecsDefined: totalSpecsDefined,
|
totalSpecsDefined: suiteBuilder.totalSpecsDefined,
|
||||||
order: order
|
order: order
|
||||||
},
|
},
|
||||||
function() {
|
function() {
|
||||||
@@ -1789,10 +1737,10 @@ getJasmineRequireObj().Env = function(j$) {
|
|||||||
topSuite.result.failedExpectations.length > 0
|
topSuite.result.failedExpectations.length > 0
|
||||||
) {
|
) {
|
||||||
overallStatus = 'failed';
|
overallStatus = 'failed';
|
||||||
} else if (focusedRunables.length > 0) {
|
} else if (suiteBuilder.focusedRunables.length > 0) {
|
||||||
overallStatus = 'incomplete';
|
overallStatus = 'incomplete';
|
||||||
incompleteReason = 'fit() or fdescribe() was found';
|
incompleteReason = 'fit() or fdescribe() was found';
|
||||||
} else if (totalSpecsDefined === 0) {
|
} else if (suiteBuilder.totalSpecsDefined === 0) {
|
||||||
overallStatus = 'incomplete';
|
overallStatus = 'incomplete';
|
||||||
incompleteReason = 'No specs found';
|
incompleteReason = 'No specs found';
|
||||||
} else {
|
} else {
|
||||||
@@ -1950,22 +1898,6 @@ getJasmineRequireObj().Env = function(j$) {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
function ensureIsFunction(fn, caller) {
|
|
||||||
if (!j$.isFunction_(fn)) {
|
|
||||||
throw new Error(
|
|
||||||
caller + ' expects a function argument; received ' + j$.getType_(fn)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function ensureIsFunctionOrAsync(fn, caller) {
|
|
||||||
if (!j$.isFunction_(fn) && !j$.isAsyncFunction_(fn)) {
|
|
||||||
throw new Error(
|
|
||||||
caller + ' expects a function argument; received ' + j$.getType_(fn)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function ensureIsNotNested(method) {
|
function ensureIsNotNested(method) {
|
||||||
const runable = currentRunable();
|
const runable = currentRunable();
|
||||||
if (runable !== null && runable !== undefined) {
|
if (runable !== null && runable !== undefined) {
|
||||||
@@ -1975,150 +1907,38 @@ getJasmineRequireObj().Env = function(j$) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function suiteFactory(description) {
|
this.describe = function(description, definitionFn) {
|
||||||
return new j$.Suite({
|
|
||||||
id: getNextSuiteId(),
|
|
||||||
description: description,
|
|
||||||
parentSuite: currentDeclarationSuite,
|
|
||||||
timer: new j$.Timer(),
|
|
||||||
expectationFactory: expectationFactory,
|
|
||||||
asyncExpectationFactory: suiteAsyncExpectationFactory,
|
|
||||||
throwOnExpectationFailure: config.stopSpecOnExpectationFailure,
|
|
||||||
autoCleanClosures: config.autoCleanClosures,
|
|
||||||
onLateError: recordLateError
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
this.describe = function(description, specDefinitions) {
|
|
||||||
ensureIsNotNested('describe');
|
ensureIsNotNested('describe');
|
||||||
ensureIsFunction(specDefinitions, 'describe');
|
return suiteBuilder.describe(description, definitionFn).metadata;
|
||||||
const suite = suiteFactory(description);
|
|
||||||
if (specDefinitions.length > 0) {
|
|
||||||
throw new Error('describe does not expect any arguments');
|
|
||||||
}
|
|
||||||
if (currentDeclarationSuite.markedExcluding) {
|
|
||||||
suite.exclude();
|
|
||||||
}
|
|
||||||
addSpecsToSuite(suite, specDefinitions);
|
|
||||||
if (suite.parentSuite && !suite.children.length) {
|
|
||||||
throw new Error(
|
|
||||||
'describe with no children (describe() or it()): ' +
|
|
||||||
suite.getFullName()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return suite.metadata;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.xdescribe = function(description, specDefinitions) {
|
this.xdescribe = function(description, definitionFn) {
|
||||||
ensureIsNotNested('xdescribe');
|
ensureIsNotNested('xdescribe');
|
||||||
ensureIsFunction(specDefinitions, 'xdescribe');
|
return suiteBuilder.xdescribe(description, definitionFn).metadata;
|
||||||
const suite = suiteFactory(description);
|
|
||||||
suite.exclude();
|
|
||||||
addSpecsToSuite(suite, specDefinitions);
|
|
||||||
return suite.metadata;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.fdescribe = function(description, specDefinitions) {
|
this.fdescribe = function(description, definitionFn) {
|
||||||
ensureIsNotNested('fdescribe');
|
ensureIsNotNested('fdescribe');
|
||||||
ensureIsFunction(specDefinitions, 'fdescribe');
|
return suiteBuilder.fdescribe(description, definitionFn).metadata;
|
||||||
const suite = suiteFactory(description);
|
|
||||||
suite.isFocused = true;
|
|
||||||
|
|
||||||
focusedRunables.push(suite.id);
|
|
||||||
unfocusAncestor();
|
|
||||||
addSpecsToSuite(suite, specDefinitions);
|
|
||||||
|
|
||||||
return suite.metadata;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function addSpecsToSuite(suite, specDefinitions) {
|
function specResultCallback(spec, result, next) {
|
||||||
const parentSuite = currentDeclarationSuite;
|
runableResources.clearForRunable(spec.id);
|
||||||
parentSuite.addChild(suite);
|
currentSpec = null;
|
||||||
currentDeclarationSuite = suite;
|
|
||||||
|
|
||||||
let declarationError = null;
|
if (result.status === 'failed') {
|
||||||
try {
|
hasFailures = true;
|
||||||
specDefinitions();
|
|
||||||
} catch (e) {
|
|
||||||
declarationError = e;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (declarationError) {
|
reportSpecDone(spec, result, next);
|
||||||
suite.handleException(declarationError);
|
|
||||||
}
|
|
||||||
|
|
||||||
currentDeclarationSuite = parentSuite;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function findFocusedAncestor(suite) {
|
function specStarted(spec, suite, next) {
|
||||||
while (suite) {
|
currentSpec = spec;
|
||||||
if (suite.isFocused) {
|
runableResources.initForRunable(spec.id, suite.id);
|
||||||
return suite.id;
|
reporter.specStarted(spec.result, next);
|
||||||
}
|
|
||||||
suite = suite.parentSuite;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function unfocusAncestor() {
|
|
||||||
const focusedAncestor = findFocusedAncestor(currentDeclarationSuite);
|
|
||||||
if (focusedAncestor) {
|
|
||||||
for (let i = 0; i < focusedRunables.length; i++) {
|
|
||||||
if (focusedRunables[i] === focusedAncestor) {
|
|
||||||
focusedRunables.splice(i, 1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const specFactory = function(description, fn, suite, timeout) {
|
|
||||||
totalSpecsDefined++;
|
|
||||||
const spec = new j$.Spec({
|
|
||||||
id: getNextSpecId(),
|
|
||||||
beforeAndAfterFns: beforeAndAfterFns(suite),
|
|
||||||
expectationFactory: expectationFactory,
|
|
||||||
asyncExpectationFactory: specAsyncExpectationFactory,
|
|
||||||
onLateError: recordLateError,
|
|
||||||
resultCallback: specResultCallback,
|
|
||||||
getSpecName: function(spec) {
|
|
||||||
return getSpecName(spec, suite);
|
|
||||||
},
|
|
||||||
onStart: specStarted,
|
|
||||||
description: description,
|
|
||||||
queueRunnerFactory: queueRunnerFactory,
|
|
||||||
userContext: function() {
|
|
||||||
return suite.clonedSharedUserContext();
|
|
||||||
},
|
|
||||||
queueableFn: {
|
|
||||||
fn: fn,
|
|
||||||
timeout: timeout || 0
|
|
||||||
},
|
|
||||||
throwOnExpectationFailure: config.stopSpecOnExpectationFailure,
|
|
||||||
autoCleanClosures: config.autoCleanClosures,
|
|
||||||
timer: new j$.Timer()
|
|
||||||
});
|
|
||||||
return spec;
|
|
||||||
|
|
||||||
function specResultCallback(result, next) {
|
|
||||||
runableResources.clearForRunable(spec.id);
|
|
||||||
currentSpec = null;
|
|
||||||
|
|
||||||
if (result.status === 'failed') {
|
|
||||||
hasFailures = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
reportSpecDone(spec, result, next);
|
|
||||||
}
|
|
||||||
|
|
||||||
function specStarted(spec, next) {
|
|
||||||
currentSpec = spec;
|
|
||||||
runableResources.initForRunable(spec.id, suite.id);
|
|
||||||
reporter.specStarted(spec.result, next);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function reportSpecDone(spec, result, next) {
|
function reportSpecDone(spec, result, next) {
|
||||||
spec.reportedDone = true;
|
spec.reportedDone = true;
|
||||||
reporter.specDone(result, next);
|
reporter.specDone(result, next);
|
||||||
@@ -2129,66 +1949,19 @@ getJasmineRequireObj().Env = function(j$) {
|
|||||||
reporter.suiteDone(result, next);
|
reporter.suiteDone(result, next);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.it_ = function(description, fn, timeout) {
|
|
||||||
ensureIsNotNested('it');
|
|
||||||
// it() sometimes doesn't have a fn argument, so only check the type if
|
|
||||||
// it's given.
|
|
||||||
if (arguments.length > 1 && typeof fn !== 'undefined') {
|
|
||||||
ensureIsFunctionOrAsync(fn, 'it');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (timeout) {
|
|
||||||
j$.util.validateTimeout(timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
const spec = specFactory(
|
|
||||||
description,
|
|
||||||
fn,
|
|
||||||
currentDeclarationSuite,
|
|
||||||
timeout
|
|
||||||
);
|
|
||||||
if (currentDeclarationSuite.markedExcluding) {
|
|
||||||
spec.exclude();
|
|
||||||
}
|
|
||||||
currentDeclarationSuite.addChild(spec);
|
|
||||||
|
|
||||||
return spec;
|
|
||||||
};
|
|
||||||
|
|
||||||
this.it = function(description, fn, timeout) {
|
this.it = function(description, fn, timeout) {
|
||||||
const spec = this.it_(description, fn, timeout);
|
ensureIsNotNested('it');
|
||||||
return spec.metadata;
|
return suiteBuilder.it(description, fn, timeout).metadata;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.xit = function(description, fn, timeout) {
|
this.xit = function(description, fn, timeout) {
|
||||||
ensureIsNotNested('xit');
|
ensureIsNotNested('xit');
|
||||||
// xit(), like it(), doesn't always have a fn argument, so only check the
|
return suiteBuilder.xit(description, fn, timeout).metadata;
|
||||||
// type when needed.
|
|
||||||
if (arguments.length > 1 && typeof fn !== 'undefined') {
|
|
||||||
ensureIsFunctionOrAsync(fn, 'xit');
|
|
||||||
}
|
|
||||||
const spec = this.it_.apply(this, arguments);
|
|
||||||
spec.exclude('Temporarily disabled with xit');
|
|
||||||
return spec.metadata;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.fit = function(description, fn, timeout) {
|
this.fit = function(description, fn, timeout) {
|
||||||
ensureIsNotNested('fit');
|
ensureIsNotNested('fit');
|
||||||
ensureIsFunctionOrAsync(fn, 'fit');
|
return suiteBuilder.fit(description, fn, timeout).metadata;
|
||||||
|
|
||||||
if (timeout) {
|
|
||||||
j$.util.validateTimeout(timeout);
|
|
||||||
}
|
|
||||||
const spec = specFactory(
|
|
||||||
description,
|
|
||||||
fn,
|
|
||||||
currentDeclarationSuite,
|
|
||||||
timeout
|
|
||||||
);
|
|
||||||
currentDeclarationSuite.addChild(spec);
|
|
||||||
focusedRunables.push(spec.id);
|
|
||||||
unfocusAncestor();
|
|
||||||
return spec.metadata;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2257,59 +2030,22 @@ getJasmineRequireObj().Env = function(j$) {
|
|||||||
|
|
||||||
this.beforeEach = function(beforeEachFunction, timeout) {
|
this.beforeEach = function(beforeEachFunction, timeout) {
|
||||||
ensureIsNotNested('beforeEach');
|
ensureIsNotNested('beforeEach');
|
||||||
ensureIsFunctionOrAsync(beforeEachFunction, 'beforeEach');
|
suiteBuilder.beforeEach(beforeEachFunction, timeout);
|
||||||
|
|
||||||
if (timeout) {
|
|
||||||
j$.util.validateTimeout(timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
currentDeclarationSuite.beforeEach({
|
|
||||||
fn: beforeEachFunction,
|
|
||||||
timeout: timeout || 0
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.beforeAll = function(beforeAllFunction, timeout) {
|
this.beforeAll = function(beforeAllFunction, timeout) {
|
||||||
ensureIsNotNested('beforeAll');
|
ensureIsNotNested('beforeAll');
|
||||||
ensureIsFunctionOrAsync(beforeAllFunction, 'beforeAll');
|
suiteBuilder.beforeAll(beforeAllFunction, timeout);
|
||||||
|
|
||||||
if (timeout) {
|
|
||||||
j$.util.validateTimeout(timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
currentDeclarationSuite.beforeAll({
|
|
||||||
fn: beforeAllFunction,
|
|
||||||
timeout: timeout || 0
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.afterEach = function(afterEachFunction, timeout) {
|
this.afterEach = function(afterEachFunction, timeout) {
|
||||||
ensureIsNotNested('afterEach');
|
ensureIsNotNested('afterEach');
|
||||||
ensureIsFunctionOrAsync(afterEachFunction, 'afterEach');
|
suiteBuilder.afterEach(afterEachFunction, timeout);
|
||||||
|
|
||||||
if (timeout) {
|
|
||||||
j$.util.validateTimeout(timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
afterEachFunction.isCleanup = true;
|
|
||||||
currentDeclarationSuite.afterEach({
|
|
||||||
fn: afterEachFunction,
|
|
||||||
timeout: timeout || 0
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.afterAll = function(afterAllFunction, timeout) {
|
this.afterAll = function(afterAllFunction, timeout) {
|
||||||
ensureIsNotNested('afterAll');
|
ensureIsNotNested('afterAll');
|
||||||
ensureIsFunctionOrAsync(afterAllFunction, 'afterAll');
|
suiteBuilder.afterAll(afterAllFunction, timeout);
|
||||||
|
|
||||||
if (timeout) {
|
|
||||||
j$.util.validateTimeout(timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
currentDeclarationSuite.afterAll({
|
|
||||||
fn: afterAllFunction,
|
|
||||||
timeout: timeout || 0
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.pending = function(message) {
|
this.pending = function(message) {
|
||||||
@@ -9899,6 +9635,311 @@ getJasmineRequireObj().Suite = function(j$) {
|
|||||||
return Suite;
|
return Suite;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
getJasmineRequireObj().SuiteBuilder = function(j$) {
|
||||||
|
class SuiteBuilder {
|
||||||
|
constructor(options) {
|
||||||
|
this.env_ = options.env;
|
||||||
|
this.expectationFactory_ = options.expectationFactory;
|
||||||
|
this.suiteAsyncExpectationFactory_ = function(actual, suite) {
|
||||||
|
return options.asyncExpectationFactory(actual, suite, 'Suite');
|
||||||
|
};
|
||||||
|
this.specAsyncExpectationFactory_ = function(actual, suite) {
|
||||||
|
return options.asyncExpectationFactory(actual, suite, 'Spec');
|
||||||
|
};
|
||||||
|
this.onLateError_ = options.onLateError;
|
||||||
|
this.specResultCallback_ = options.specResultCallback;
|
||||||
|
this.specStarted_ = options.specStarted;
|
||||||
|
this.queueRunnerFactory_ = options.queueRunnerFactory;
|
||||||
|
|
||||||
|
this.nextSuiteId_ = 0;
|
||||||
|
this.nextSpecId_ = 0;
|
||||||
|
|
||||||
|
this.topSuite = this.suiteFactory_('Jasmine__TopLevel__Suite');
|
||||||
|
this.currentDeclarationSuite_ = this.topSuite;
|
||||||
|
this.totalSpecsDefined = 0;
|
||||||
|
this.focusedRunables = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
describe(description, definitionFn) {
|
||||||
|
ensureIsFunction(definitionFn, 'describe');
|
||||||
|
const suite = this.suiteFactory_(description);
|
||||||
|
if (definitionFn.length > 0) {
|
||||||
|
throw new Error('describe does not expect any arguments');
|
||||||
|
}
|
||||||
|
if (this.currentDeclarationSuite_.markedExcluding) {
|
||||||
|
suite.exclude();
|
||||||
|
}
|
||||||
|
this.addSpecsToSuite_(suite, definitionFn);
|
||||||
|
if (suite.parentSuite && !suite.children.length) {
|
||||||
|
throw new Error(
|
||||||
|
`describe with no children (describe() or it()): ${suite.getFullName()}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return suite;
|
||||||
|
}
|
||||||
|
|
||||||
|
fdescribe(description, definitionFn) {
|
||||||
|
ensureIsFunction(definitionFn, 'fdescribe');
|
||||||
|
const suite = this.suiteFactory_(description);
|
||||||
|
suite.isFocused = true;
|
||||||
|
|
||||||
|
this.focusedRunables.push(suite.id);
|
||||||
|
this.unfocusAncestor_();
|
||||||
|
this.addSpecsToSuite_(suite, definitionFn);
|
||||||
|
|
||||||
|
return suite;
|
||||||
|
}
|
||||||
|
|
||||||
|
xdescribe(description, definitionFn) {
|
||||||
|
ensureIsFunction(definitionFn, 'xdescribe');
|
||||||
|
const suite = this.suiteFactory_(description);
|
||||||
|
suite.exclude();
|
||||||
|
this.addSpecsToSuite_(suite, definitionFn);
|
||||||
|
|
||||||
|
return suite;
|
||||||
|
}
|
||||||
|
|
||||||
|
it(description, fn, timeout) {
|
||||||
|
// it() sometimes doesn't have a fn argument, so only check the type if
|
||||||
|
// it's given.
|
||||||
|
if (arguments.length > 1 && typeof fn !== 'undefined') {
|
||||||
|
ensureIsFunctionOrAsync(fn, 'it');
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.it_(description, fn, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
xit(description, fn, timeout) {
|
||||||
|
// xit(), like it(), doesn't always have a fn argument, so only check the
|
||||||
|
// type when needed.
|
||||||
|
if (arguments.length > 1 && typeof fn !== 'undefined') {
|
||||||
|
ensureIsFunctionOrAsync(fn, 'xit');
|
||||||
|
}
|
||||||
|
const spec = this.it_(description, fn, timeout);
|
||||||
|
spec.exclude('Temporarily disabled with xit');
|
||||||
|
return spec;
|
||||||
|
}
|
||||||
|
|
||||||
|
fit(description, fn, timeout) {
|
||||||
|
// Unlike it and xit, the function is required because it doesn't make
|
||||||
|
// sense to focus on nothing.
|
||||||
|
ensureIsFunctionOrAsync(fn, 'fit');
|
||||||
|
|
||||||
|
if (timeout) {
|
||||||
|
j$.util.validateTimeout(timeout);
|
||||||
|
}
|
||||||
|
const spec = this.specFactory_(description, fn, timeout);
|
||||||
|
this.currentDeclarationSuite_.addChild(spec);
|
||||||
|
this.focusedRunables.push(spec.id);
|
||||||
|
this.unfocusAncestor_();
|
||||||
|
return spec;
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(beforeEachFunction, timeout) {
|
||||||
|
ensureIsFunctionOrAsync(beforeEachFunction, 'beforeEach');
|
||||||
|
|
||||||
|
if (timeout) {
|
||||||
|
j$.util.validateTimeout(timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.currentDeclarationSuite_.beforeEach({
|
||||||
|
fn: beforeEachFunction,
|
||||||
|
timeout: timeout || 0
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeAll(beforeAllFunction, timeout) {
|
||||||
|
ensureIsFunctionOrAsync(beforeAllFunction, 'beforeAll');
|
||||||
|
|
||||||
|
if (timeout) {
|
||||||
|
j$.util.validateTimeout(timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.currentDeclarationSuite_.beforeAll({
|
||||||
|
fn: beforeAllFunction,
|
||||||
|
timeout: timeout || 0
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
afterEach(afterEachFunction, timeout) {
|
||||||
|
ensureIsFunctionOrAsync(afterEachFunction, 'afterEach');
|
||||||
|
|
||||||
|
if (timeout) {
|
||||||
|
j$.util.validateTimeout(timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
afterEachFunction.isCleanup = true;
|
||||||
|
this.currentDeclarationSuite_.afterEach({
|
||||||
|
fn: afterEachFunction,
|
||||||
|
timeout: timeout || 0
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
afterAll(afterAllFunction, timeout) {
|
||||||
|
ensureIsFunctionOrAsync(afterAllFunction, 'afterAll');
|
||||||
|
|
||||||
|
if (timeout) {
|
||||||
|
j$.util.validateTimeout(timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.currentDeclarationSuite_.afterAll({
|
||||||
|
fn: afterAllFunction,
|
||||||
|
timeout: timeout || 0
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
it_(description, fn, timeout) {
|
||||||
|
if (timeout) {
|
||||||
|
j$.util.validateTimeout(timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
const spec = this.specFactory_(description, fn, timeout);
|
||||||
|
if (this.currentDeclarationSuite_.markedExcluding) {
|
||||||
|
spec.exclude();
|
||||||
|
}
|
||||||
|
this.currentDeclarationSuite_.addChild(spec);
|
||||||
|
|
||||||
|
return spec;
|
||||||
|
}
|
||||||
|
|
||||||
|
suiteFactory_(description) {
|
||||||
|
const config = this.env_.configuration();
|
||||||
|
return new j$.Suite({
|
||||||
|
id: 'suite' + this.nextSuiteId_++,
|
||||||
|
description,
|
||||||
|
parentSuite: this.currentDeclarationSuite_,
|
||||||
|
timer: new j$.Timer(),
|
||||||
|
expectationFactory: this.expectationFactory_,
|
||||||
|
asyncExpectationFactory: this.suiteAsyncExpectationFactory_,
|
||||||
|
throwOnExpectationFailure: config.stopSpecOnExpectationFailure,
|
||||||
|
autoCleanClosures: config.autoCleanClosures,
|
||||||
|
onLateError: this.onLateError_
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
addSpecsToSuite_(suite, definitionFn) {
|
||||||
|
const parentSuite = this.currentDeclarationSuite_;
|
||||||
|
parentSuite.addChild(suite);
|
||||||
|
this.currentDeclarationSuite_ = suite;
|
||||||
|
|
||||||
|
try {
|
||||||
|
definitionFn();
|
||||||
|
} catch (e) {
|
||||||
|
suite.handleException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.currentDeclarationSuite_ = parentSuite;
|
||||||
|
}
|
||||||
|
|
||||||
|
specFactory_(description, fn, timeout) {
|
||||||
|
this.totalSpecsDefined++;
|
||||||
|
const config = this.env_.configuration();
|
||||||
|
const suite = this.currentDeclarationSuite_;
|
||||||
|
const spec = new j$.Spec({
|
||||||
|
id: 'spec' + this.nextSpecId_++,
|
||||||
|
beforeAndAfterFns: beforeAndAfterFns(suite),
|
||||||
|
expectationFactory: this.expectationFactory_,
|
||||||
|
asyncExpectationFactory: this.specAsyncExpectationFactory_,
|
||||||
|
onLateError: this.onLateError_,
|
||||||
|
resultCallback: (result, next) => {
|
||||||
|
this.specResultCallback_(spec, result, next);
|
||||||
|
},
|
||||||
|
getSpecName: function(spec) {
|
||||||
|
return getSpecName(spec, suite);
|
||||||
|
},
|
||||||
|
onStart: (spec, next) => this.specStarted_(spec, suite, next),
|
||||||
|
description: description,
|
||||||
|
queueRunnerFactory: this.queueRunnerFactory_,
|
||||||
|
userContext: function() {
|
||||||
|
return suite.clonedSharedUserContext();
|
||||||
|
},
|
||||||
|
queueableFn: {
|
||||||
|
fn: fn,
|
||||||
|
timeout: timeout || 0
|
||||||
|
},
|
||||||
|
throwOnExpectationFailure: config.stopSpecOnExpectationFailure,
|
||||||
|
autoCleanClosures: config.autoCleanClosures,
|
||||||
|
timer: new j$.Timer()
|
||||||
|
});
|
||||||
|
return spec;
|
||||||
|
}
|
||||||
|
|
||||||
|
unfocusAncestor_() {
|
||||||
|
const focusedAncestor = findFocusedAncestor(
|
||||||
|
this.currentDeclarationSuite_
|
||||||
|
);
|
||||||
|
|
||||||
|
if (focusedAncestor) {
|
||||||
|
for (let i = 0; i < this.focusedRunables.length; i++) {
|
||||||
|
if (this.focusedRunables[i] === focusedAncestor) {
|
||||||
|
this.focusedRunables.splice(i, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function findFocusedAncestor(suite) {
|
||||||
|
while (suite) {
|
||||||
|
if (suite.isFocused) {
|
||||||
|
return suite.id;
|
||||||
|
}
|
||||||
|
suite = suite.parentSuite;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function ensureIsFunction(fn, caller) {
|
||||||
|
if (!j$.isFunction_(fn)) {
|
||||||
|
throw new Error(
|
||||||
|
caller + ' expects a function argument; received ' + j$.getType_(fn)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function ensureIsFunctionOrAsync(fn, caller) {
|
||||||
|
if (!j$.isFunction_(fn) && !j$.isAsyncFunction_(fn)) {
|
||||||
|
throw new Error(
|
||||||
|
caller + ' expects a function argument; received ' + j$.getType_(fn)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function beforeAndAfterFns(targetSuite) {
|
||||||
|
return function() {
|
||||||
|
let befores = [],
|
||||||
|
afters = [],
|
||||||
|
suite = targetSuite;
|
||||||
|
|
||||||
|
while (suite) {
|
||||||
|
befores = befores.concat(suite.beforeFns);
|
||||||
|
afters = afters.concat(suite.afterFns);
|
||||||
|
|
||||||
|
suite = suite.parentSuite;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
befores: befores.reverse(),
|
||||||
|
afters: afters
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSpecName(spec, suite) {
|
||||||
|
const fullName = [spec.description],
|
||||||
|
suiteFullName = suite.getFullName();
|
||||||
|
|
||||||
|
if (suiteFullName !== '') {
|
||||||
|
fullName.unshift(suiteFullName);
|
||||||
|
}
|
||||||
|
return fullName.join(' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
return SuiteBuilder;
|
||||||
|
};
|
||||||
|
|
||||||
getJasmineRequireObj().Timer = function() {
|
getJasmineRequireObj().Timer = function() {
|
||||||
const defaultNow = (function(Date) {
|
const defaultNow = (function(Date) {
|
||||||
return function() {
|
return function() {
|
||||||
|
|||||||
@@ -316,7 +316,7 @@ describe('Env', function() {
|
|||||||
|
|
||||||
it('calls spec.exclude with "Temporarily disabled with xit"', function() {
|
it('calls spec.exclude with "Temporarily disabled with xit"', function() {
|
||||||
const excludeSpy = jasmine.createSpy();
|
const excludeSpy = jasmine.createSpy();
|
||||||
spyOn(env, 'it_').and.returnValue({
|
spyOn(jasmineUnderTest.SuiteBuilder.prototype, 'it_').and.returnValue({
|
||||||
exclude: excludeSpy
|
exclude: excludeSpy
|
||||||
});
|
});
|
||||||
env.xit('foo', function() {});
|
env.xit('foo', function() {});
|
||||||
@@ -327,7 +327,7 @@ describe('Env', function() {
|
|||||||
const pendSpy = jasmine.createSpy();
|
const pendSpy = jasmine.createSpy();
|
||||||
const realExclude = jasmineUnderTest.Spec.prototype.exclude;
|
const realExclude = jasmineUnderTest.Spec.prototype.exclude;
|
||||||
|
|
||||||
spyOn(env, 'it_').and.returnValue({
|
spyOn(jasmineUnderTest.SuiteBuilder.prototype, 'it_').and.returnValue({
|
||||||
exclude: realExclude,
|
exclude: realExclude,
|
||||||
pend: pendSpy
|
pend: pendSpy
|
||||||
});
|
});
|
||||||
|
|||||||
178
spec/core/SuiteBuilderSpec.js
Normal file
178
spec/core/SuiteBuilderSpec.js
Normal file
@@ -0,0 +1,178 @@
|
|||||||
|
describe('SuiteBuilder', function() {
|
||||||
|
beforeEach(function() {
|
||||||
|
// Rethrow exceptions to ease debugging
|
||||||
|
spyOn(jasmineUnderTest.Suite.prototype, 'handleException').and.callFake(
|
||||||
|
function(e) {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
spyOn(jasmineUnderTest.Spec.prototype, 'handleException').and.callFake(
|
||||||
|
function(e) {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('creates the top suite', function() {
|
||||||
|
const env = { configuration: () => ({}) };
|
||||||
|
const suiteBuilder = new jasmineUnderTest.SuiteBuilder({ env });
|
||||||
|
|
||||||
|
expect(suiteBuilder.topSuite).toBeInstanceOf(jasmineUnderTest.Suite);
|
||||||
|
expect(suiteBuilder.topSuite.description).toEqual(
|
||||||
|
'Jasmine__TopLevel__Suite'
|
||||||
|
);
|
||||||
|
expect(suiteBuilder.topSuite.parentSuite).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#describe', function() {
|
||||||
|
definesSuites('describe');
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#fdescribe', function() {
|
||||||
|
definesSuites('fdescribe');
|
||||||
|
|
||||||
|
it('focuses the suite', function() {
|
||||||
|
const env = { configuration: () => ({}) };
|
||||||
|
const suiteBuilder = new jasmineUnderTest.SuiteBuilder({ env });
|
||||||
|
|
||||||
|
const suite = suiteBuilder.fdescribe('a suite', function() {
|
||||||
|
suiteBuilder.it('a spec');
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(suite.isFocused).toBeTrue();
|
||||||
|
expect(suiteBuilder.focusedRunables).toEqual([suite.id]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('unfocuses any focused ancestor suite', function() {
|
||||||
|
const env = { configuration: () => ({}) };
|
||||||
|
const suiteBuilder = new jasmineUnderTest.SuiteBuilder({ env });
|
||||||
|
|
||||||
|
const grandparent = suiteBuilder.fdescribe('a suite', function() {
|
||||||
|
suiteBuilder.describe('another suite', function() {
|
||||||
|
suiteBuilder.fdescribe('the focused suite', function() {
|
||||||
|
suiteBuilder.it('a spec');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(suiteBuilder.focusedRunables).not.toContain(grandparent.id);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#xdescribe', function() {
|
||||||
|
definesSuites('xdescribe');
|
||||||
|
|
||||||
|
it('excludes the suite', function() {
|
||||||
|
const env = { configuration: () => ({}) };
|
||||||
|
const suiteBuilder = new jasmineUnderTest.SuiteBuilder({ env });
|
||||||
|
|
||||||
|
const suite = suiteBuilder.xdescribe('a suite', function() {
|
||||||
|
suiteBuilder.it('a spec');
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(suite.markedExcluding).toBeTrue();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('causes child suites to be marked excluded', function() {
|
||||||
|
const env = { configuration: () => ({}) };
|
||||||
|
const suiteBuilder = new jasmineUnderTest.SuiteBuilder({ env });
|
||||||
|
|
||||||
|
let suite;
|
||||||
|
suiteBuilder.xdescribe('a suite', function() {
|
||||||
|
suite = suiteBuilder.describe('another suite', function() {
|
||||||
|
suiteBuilder.it('a spec');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(suite.markedExcluding).toBeTrue();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#it', function() {
|
||||||
|
definesSpecs('it');
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#fit', function() {
|
||||||
|
definesSpecs('fit');
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#xit', function() {
|
||||||
|
definesSpecs('xit');
|
||||||
|
});
|
||||||
|
|
||||||
|
function definesSuites(fnName) {
|
||||||
|
it('links suites to their parents and children', function() {
|
||||||
|
const env = { configuration: () => ({}) };
|
||||||
|
const suiteBuilder = new jasmineUnderTest.SuiteBuilder({ env });
|
||||||
|
|
||||||
|
let child;
|
||||||
|
const parent = suiteBuilder[fnName]('parent', function() {
|
||||||
|
child = suiteBuilder[fnName]('child', function() {
|
||||||
|
suiteBuilder.it('a spec');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(suiteBuilder.topSuite.children).toEqual([sameInstanceAs(parent)]);
|
||||||
|
expect(parent.children).toEqual([sameInstanceAs(child)]);
|
||||||
|
expect(child.parentSuite).toBe(parent);
|
||||||
|
expect(parent.parentSuite).toBe(suiteBuilder.topSuite);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('gives each suite a unique ID', function() {
|
||||||
|
const env = { configuration: () => ({}) };
|
||||||
|
const suiteBuilder = new jasmineUnderTest.SuiteBuilder({ env });
|
||||||
|
|
||||||
|
let child;
|
||||||
|
const parent = suiteBuilder[fnName]('parent', function() {
|
||||||
|
child = suiteBuilder[fnName]('child', function() {
|
||||||
|
suiteBuilder.it('a spec');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const ids = [suiteBuilder.topSuite.id, parent.id, child.id];
|
||||||
|
|
||||||
|
for (const id of ids) {
|
||||||
|
expect(id).toMatch(/^suite[0-9]$/);
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(new Set(ids).size).toEqual(3);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function definesSpecs(fnName) {
|
||||||
|
it('adds the spec to its suite', function() {
|
||||||
|
const env = { configuration: () => ({}) };
|
||||||
|
const suiteBuilder = new jasmineUnderTest.SuiteBuilder({ env });
|
||||||
|
|
||||||
|
let spec;
|
||||||
|
const suite = suiteBuilder.describe('a suite', function() {
|
||||||
|
spec = suiteBuilder[fnName]('a spec', function() {});
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(suite.children).toEqual([sameInstanceAs(spec)]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('gives each spec a unique ID', function() {
|
||||||
|
const env = { configuration: () => ({}) };
|
||||||
|
const suiteBuilder = new jasmineUnderTest.SuiteBuilder({ env });
|
||||||
|
|
||||||
|
const spec1 = suiteBuilder[fnName]('a spec', function() {});
|
||||||
|
const spec2 = suiteBuilder[fnName]('another spec', function() {});
|
||||||
|
|
||||||
|
expect(spec1.id).toMatch(/^spec[0-9]+$/);
|
||||||
|
expect(spec2.id).toMatch(/^spec[0-9]+$/);
|
||||||
|
expect(spec1.id).not.toEqual(spec2.id);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function sameInstanceAs(expected) {
|
||||||
|
return {
|
||||||
|
asymmetricMatch: function(actual) {
|
||||||
|
return actual === expected;
|
||||||
|
},
|
||||||
|
jasmineToString: function(pp) {
|
||||||
|
return '<same instance as ' + pp(expected) + '>';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
345
src/core/Env.js
345
src/core/Env.js
@@ -13,8 +13,6 @@ getJasmineRequireObj().Env = function(j$) {
|
|||||||
const self = this;
|
const self = this;
|
||||||
const global = options.global || j$.getGlobal();
|
const global = options.global || j$.getGlobal();
|
||||||
|
|
||||||
let totalSpecsDefined = 0;
|
|
||||||
|
|
||||||
const realSetTimeout = global.setTimeout;
|
const realSetTimeout = global.setTimeout;
|
||||||
const realClearTimeout = global.clearTimeout;
|
const realClearTimeout = global.clearTimeout;
|
||||||
const clearStack = j$.getClearStack(global);
|
const clearStack = j$.getClearStack(global);
|
||||||
@@ -31,14 +29,11 @@ getJasmineRequireObj().Env = function(j$) {
|
|||||||
return r ? r.id : null;
|
return r ? r.id : null;
|
||||||
});
|
});
|
||||||
|
|
||||||
let topSuite;
|
|
||||||
let currentSpec = null;
|
let currentSpec = null;
|
||||||
const currentlyExecutingSuites = [];
|
const currentlyExecutingSuites = [];
|
||||||
const focusedRunables = [];
|
|
||||||
let currentDeclarationSuite = null;
|
|
||||||
let hasFailures = false;
|
let hasFailures = false;
|
||||||
let deprecator;
|
|
||||||
let reporter;
|
let reporter;
|
||||||
|
let topSuite;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This represents the available options to configure Jasmine.
|
* This represents the available options to configure Jasmine.
|
||||||
@@ -258,18 +253,6 @@ getJasmineRequireObj().Env = function(j$) {
|
|||||||
j$.Expectation.addCoreMatchers(j$.matchers);
|
j$.Expectation.addCoreMatchers(j$.matchers);
|
||||||
j$.Expectation.addAsyncCoreMatchers(j$.asyncMatchers);
|
j$.Expectation.addAsyncCoreMatchers(j$.asyncMatchers);
|
||||||
|
|
||||||
let nextSpecId = 0;
|
|
||||||
|
|
||||||
function getNextSpecId() {
|
|
||||||
return 'spec' + nextSpecId++;
|
|
||||||
}
|
|
||||||
|
|
||||||
let nextSuiteId = 0;
|
|
||||||
|
|
||||||
function getNextSuiteId() {
|
|
||||||
return 'suite' + nextSuiteId++;
|
|
||||||
}
|
|
||||||
|
|
||||||
const expectationFactory = function(actual, spec) {
|
const expectationFactory = function(actual, spec) {
|
||||||
return j$.Expectation.factory({
|
return j$.Expectation.factory({
|
||||||
matchersUtil: runableResources.makeMatchersUtil(),
|
matchersUtil: runableResources.makeMatchersUtil(),
|
||||||
@@ -363,43 +346,6 @@ getJasmineRequireObj().Env = function(j$) {
|
|||||||
return spec.addExpectationResult(passed, result);
|
return spec.addExpectationResult(passed, result);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const suiteAsyncExpectationFactory = function(actual, suite) {
|
|
||||||
return asyncExpectationFactory(actual, suite, 'Suite');
|
|
||||||
};
|
|
||||||
|
|
||||||
const specAsyncExpectationFactory = function(actual, suite) {
|
|
||||||
return asyncExpectationFactory(actual, suite, 'Spec');
|
|
||||||
};
|
|
||||||
|
|
||||||
function beforeAndAfterFns(targetSuite) {
|
|
||||||
return function() {
|
|
||||||
let befores = [],
|
|
||||||
afters = [],
|
|
||||||
suite = targetSuite;
|
|
||||||
|
|
||||||
while (suite) {
|
|
||||||
befores = befores.concat(suite.beforeFns);
|
|
||||||
afters = afters.concat(suite.afterFns);
|
|
||||||
|
|
||||||
suite = suite.parentSuite;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
befores: befores.reverse(),
|
|
||||||
afters: afters
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function getSpecName(spec, suite) {
|
|
||||||
const fullName = [spec.description],
|
|
||||||
suiteFullName = suite.getFullName();
|
|
||||||
|
|
||||||
if (suiteFullName !== '') {
|
|
||||||
fullName.unshift(suiteFullName);
|
|
||||||
}
|
|
||||||
return fullName.join(' ');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Causes a deprecation warning to be logged to the console and reported to
|
* Causes a deprecation warning to be logged to the console and reported to
|
||||||
@@ -461,16 +407,17 @@ getJasmineRequireObj().Env = function(j$) {
|
|||||||
new j$.QueueRunner(options).execute(args);
|
new j$.QueueRunner(options).execute(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
topSuite = new j$.Suite({
|
const suiteBuilder = new j$.SuiteBuilder({
|
||||||
id: getNextSuiteId(),
|
env: this,
|
||||||
description: 'Jasmine__TopLevel__Suite',
|
expectationFactory,
|
||||||
expectationFactory: expectationFactory,
|
asyncExpectationFactory,
|
||||||
asyncExpectationFactory: suiteAsyncExpectationFactory,
|
onLateError: recordLateError,
|
||||||
autoCleanClosures: config.autoCleanClosures,
|
specResultCallback,
|
||||||
onLateError: recordLateError
|
specStarted,
|
||||||
|
queueRunnerFactory
|
||||||
});
|
});
|
||||||
deprecator = new j$.Deprecator(topSuite);
|
topSuite = suiteBuilder.topSuite;
|
||||||
currentDeclarationSuite = topSuite;
|
const deprecator = new j$.Deprecator(topSuite);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides the root suite, through which all suites and specs can be
|
* Provides the root suite, through which all suites and specs can be
|
||||||
@@ -600,8 +547,8 @@ getJasmineRequireObj().Env = function(j$) {
|
|||||||
installGlobalErrors();
|
installGlobalErrors();
|
||||||
|
|
||||||
if (!runablesToRun) {
|
if (!runablesToRun) {
|
||||||
if (focusedRunables.length) {
|
if (suiteBuilder.focusedRunables.length) {
|
||||||
runablesToRun = focusedRunables;
|
runablesToRun = suiteBuilder.focusedRunables;
|
||||||
} else {
|
} else {
|
||||||
runablesToRun = [topSuite.id];
|
runablesToRun = [topSuite.id];
|
||||||
}
|
}
|
||||||
@@ -681,7 +628,7 @@ getJasmineRequireObj().Env = function(j$) {
|
|||||||
*/
|
*/
|
||||||
reporter.jasmineStarted(
|
reporter.jasmineStarted(
|
||||||
{
|
{
|
||||||
totalSpecsDefined: totalSpecsDefined,
|
totalSpecsDefined: suiteBuilder.totalSpecsDefined,
|
||||||
order: order
|
order: order
|
||||||
},
|
},
|
||||||
function() {
|
function() {
|
||||||
@@ -702,10 +649,10 @@ getJasmineRequireObj().Env = function(j$) {
|
|||||||
topSuite.result.failedExpectations.length > 0
|
topSuite.result.failedExpectations.length > 0
|
||||||
) {
|
) {
|
||||||
overallStatus = 'failed';
|
overallStatus = 'failed';
|
||||||
} else if (focusedRunables.length > 0) {
|
} else if (suiteBuilder.focusedRunables.length > 0) {
|
||||||
overallStatus = 'incomplete';
|
overallStatus = 'incomplete';
|
||||||
incompleteReason = 'fit() or fdescribe() was found';
|
incompleteReason = 'fit() or fdescribe() was found';
|
||||||
} else if (totalSpecsDefined === 0) {
|
} else if (suiteBuilder.totalSpecsDefined === 0) {
|
||||||
overallStatus = 'incomplete';
|
overallStatus = 'incomplete';
|
||||||
incompleteReason = 'No specs found';
|
incompleteReason = 'No specs found';
|
||||||
} else {
|
} else {
|
||||||
@@ -863,22 +810,6 @@ getJasmineRequireObj().Env = function(j$) {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
function ensureIsFunction(fn, caller) {
|
|
||||||
if (!j$.isFunction_(fn)) {
|
|
||||||
throw new Error(
|
|
||||||
caller + ' expects a function argument; received ' + j$.getType_(fn)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function ensureIsFunctionOrAsync(fn, caller) {
|
|
||||||
if (!j$.isFunction_(fn) && !j$.isAsyncFunction_(fn)) {
|
|
||||||
throw new Error(
|
|
||||||
caller + ' expects a function argument; received ' + j$.getType_(fn)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function ensureIsNotNested(method) {
|
function ensureIsNotNested(method) {
|
||||||
const runable = currentRunable();
|
const runable = currentRunable();
|
||||||
if (runable !== null && runable !== undefined) {
|
if (runable !== null && runable !== undefined) {
|
||||||
@@ -888,150 +819,38 @@ getJasmineRequireObj().Env = function(j$) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function suiteFactory(description) {
|
this.describe = function(description, definitionFn) {
|
||||||
return new j$.Suite({
|
|
||||||
id: getNextSuiteId(),
|
|
||||||
description: description,
|
|
||||||
parentSuite: currentDeclarationSuite,
|
|
||||||
timer: new j$.Timer(),
|
|
||||||
expectationFactory: expectationFactory,
|
|
||||||
asyncExpectationFactory: suiteAsyncExpectationFactory,
|
|
||||||
throwOnExpectationFailure: config.stopSpecOnExpectationFailure,
|
|
||||||
autoCleanClosures: config.autoCleanClosures,
|
|
||||||
onLateError: recordLateError
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
this.describe = function(description, specDefinitions) {
|
|
||||||
ensureIsNotNested('describe');
|
ensureIsNotNested('describe');
|
||||||
ensureIsFunction(specDefinitions, 'describe');
|
return suiteBuilder.describe(description, definitionFn).metadata;
|
||||||
const suite = suiteFactory(description);
|
|
||||||
if (specDefinitions.length > 0) {
|
|
||||||
throw new Error('describe does not expect any arguments');
|
|
||||||
}
|
|
||||||
if (currentDeclarationSuite.markedExcluding) {
|
|
||||||
suite.exclude();
|
|
||||||
}
|
|
||||||
addSpecsToSuite(suite, specDefinitions);
|
|
||||||
if (suite.parentSuite && !suite.children.length) {
|
|
||||||
throw new Error(
|
|
||||||
'describe with no children (describe() or it()): ' +
|
|
||||||
suite.getFullName()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return suite.metadata;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.xdescribe = function(description, specDefinitions) {
|
this.xdescribe = function(description, definitionFn) {
|
||||||
ensureIsNotNested('xdescribe');
|
ensureIsNotNested('xdescribe');
|
||||||
ensureIsFunction(specDefinitions, 'xdescribe');
|
return suiteBuilder.xdescribe(description, definitionFn).metadata;
|
||||||
const suite = suiteFactory(description);
|
|
||||||
suite.exclude();
|
|
||||||
addSpecsToSuite(suite, specDefinitions);
|
|
||||||
return suite.metadata;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.fdescribe = function(description, specDefinitions) {
|
this.fdescribe = function(description, definitionFn) {
|
||||||
ensureIsNotNested('fdescribe');
|
ensureIsNotNested('fdescribe');
|
||||||
ensureIsFunction(specDefinitions, 'fdescribe');
|
return suiteBuilder.fdescribe(description, definitionFn).metadata;
|
||||||
const suite = suiteFactory(description);
|
|
||||||
suite.isFocused = true;
|
|
||||||
|
|
||||||
focusedRunables.push(suite.id);
|
|
||||||
unfocusAncestor();
|
|
||||||
addSpecsToSuite(suite, specDefinitions);
|
|
||||||
|
|
||||||
return suite.metadata;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function addSpecsToSuite(suite, specDefinitions) {
|
function specResultCallback(spec, result, next) {
|
||||||
const parentSuite = currentDeclarationSuite;
|
runableResources.clearForRunable(spec.id);
|
||||||
parentSuite.addChild(suite);
|
currentSpec = null;
|
||||||
currentDeclarationSuite = suite;
|
|
||||||
|
|
||||||
let declarationError = null;
|
if (result.status === 'failed') {
|
||||||
try {
|
hasFailures = true;
|
||||||
specDefinitions();
|
|
||||||
} catch (e) {
|
|
||||||
declarationError = e;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (declarationError) {
|
reportSpecDone(spec, result, next);
|
||||||
suite.handleException(declarationError);
|
|
||||||
}
|
|
||||||
|
|
||||||
currentDeclarationSuite = parentSuite;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function findFocusedAncestor(suite) {
|
function specStarted(spec, suite, next) {
|
||||||
while (suite) {
|
currentSpec = spec;
|
||||||
if (suite.isFocused) {
|
runableResources.initForRunable(spec.id, suite.id);
|
||||||
return suite.id;
|
reporter.specStarted(spec.result, next);
|
||||||
}
|
|
||||||
suite = suite.parentSuite;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function unfocusAncestor() {
|
|
||||||
const focusedAncestor = findFocusedAncestor(currentDeclarationSuite);
|
|
||||||
if (focusedAncestor) {
|
|
||||||
for (let i = 0; i < focusedRunables.length; i++) {
|
|
||||||
if (focusedRunables[i] === focusedAncestor) {
|
|
||||||
focusedRunables.splice(i, 1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const specFactory = function(description, fn, suite, timeout) {
|
|
||||||
totalSpecsDefined++;
|
|
||||||
const spec = new j$.Spec({
|
|
||||||
id: getNextSpecId(),
|
|
||||||
beforeAndAfterFns: beforeAndAfterFns(suite),
|
|
||||||
expectationFactory: expectationFactory,
|
|
||||||
asyncExpectationFactory: specAsyncExpectationFactory,
|
|
||||||
onLateError: recordLateError,
|
|
||||||
resultCallback: specResultCallback,
|
|
||||||
getSpecName: function(spec) {
|
|
||||||
return getSpecName(spec, suite);
|
|
||||||
},
|
|
||||||
onStart: specStarted,
|
|
||||||
description: description,
|
|
||||||
queueRunnerFactory: queueRunnerFactory,
|
|
||||||
userContext: function() {
|
|
||||||
return suite.clonedSharedUserContext();
|
|
||||||
},
|
|
||||||
queueableFn: {
|
|
||||||
fn: fn,
|
|
||||||
timeout: timeout || 0
|
|
||||||
},
|
|
||||||
throwOnExpectationFailure: config.stopSpecOnExpectationFailure,
|
|
||||||
autoCleanClosures: config.autoCleanClosures,
|
|
||||||
timer: new j$.Timer()
|
|
||||||
});
|
|
||||||
return spec;
|
|
||||||
|
|
||||||
function specResultCallback(result, next) {
|
|
||||||
runableResources.clearForRunable(spec.id);
|
|
||||||
currentSpec = null;
|
|
||||||
|
|
||||||
if (result.status === 'failed') {
|
|
||||||
hasFailures = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
reportSpecDone(spec, result, next);
|
|
||||||
}
|
|
||||||
|
|
||||||
function specStarted(spec, next) {
|
|
||||||
currentSpec = spec;
|
|
||||||
runableResources.initForRunable(spec.id, suite.id);
|
|
||||||
reporter.specStarted(spec.result, next);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function reportSpecDone(spec, result, next) {
|
function reportSpecDone(spec, result, next) {
|
||||||
spec.reportedDone = true;
|
spec.reportedDone = true;
|
||||||
reporter.specDone(result, next);
|
reporter.specDone(result, next);
|
||||||
@@ -1042,66 +861,19 @@ getJasmineRequireObj().Env = function(j$) {
|
|||||||
reporter.suiteDone(result, next);
|
reporter.suiteDone(result, next);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.it_ = function(description, fn, timeout) {
|
|
||||||
ensureIsNotNested('it');
|
|
||||||
// it() sometimes doesn't have a fn argument, so only check the type if
|
|
||||||
// it's given.
|
|
||||||
if (arguments.length > 1 && typeof fn !== 'undefined') {
|
|
||||||
ensureIsFunctionOrAsync(fn, 'it');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (timeout) {
|
|
||||||
j$.util.validateTimeout(timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
const spec = specFactory(
|
|
||||||
description,
|
|
||||||
fn,
|
|
||||||
currentDeclarationSuite,
|
|
||||||
timeout
|
|
||||||
);
|
|
||||||
if (currentDeclarationSuite.markedExcluding) {
|
|
||||||
spec.exclude();
|
|
||||||
}
|
|
||||||
currentDeclarationSuite.addChild(spec);
|
|
||||||
|
|
||||||
return spec;
|
|
||||||
};
|
|
||||||
|
|
||||||
this.it = function(description, fn, timeout) {
|
this.it = function(description, fn, timeout) {
|
||||||
const spec = this.it_(description, fn, timeout);
|
ensureIsNotNested('it');
|
||||||
return spec.metadata;
|
return suiteBuilder.it(description, fn, timeout).metadata;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.xit = function(description, fn, timeout) {
|
this.xit = function(description, fn, timeout) {
|
||||||
ensureIsNotNested('xit');
|
ensureIsNotNested('xit');
|
||||||
// xit(), like it(), doesn't always have a fn argument, so only check the
|
return suiteBuilder.xit(description, fn, timeout).metadata;
|
||||||
// type when needed.
|
|
||||||
if (arguments.length > 1 && typeof fn !== 'undefined') {
|
|
||||||
ensureIsFunctionOrAsync(fn, 'xit');
|
|
||||||
}
|
|
||||||
const spec = this.it_.apply(this, arguments);
|
|
||||||
spec.exclude('Temporarily disabled with xit');
|
|
||||||
return spec.metadata;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.fit = function(description, fn, timeout) {
|
this.fit = function(description, fn, timeout) {
|
||||||
ensureIsNotNested('fit');
|
ensureIsNotNested('fit');
|
||||||
ensureIsFunctionOrAsync(fn, 'fit');
|
return suiteBuilder.fit(description, fn, timeout).metadata;
|
||||||
|
|
||||||
if (timeout) {
|
|
||||||
j$.util.validateTimeout(timeout);
|
|
||||||
}
|
|
||||||
const spec = specFactory(
|
|
||||||
description,
|
|
||||||
fn,
|
|
||||||
currentDeclarationSuite,
|
|
||||||
timeout
|
|
||||||
);
|
|
||||||
currentDeclarationSuite.addChild(spec);
|
|
||||||
focusedRunables.push(spec.id);
|
|
||||||
unfocusAncestor();
|
|
||||||
return spec.metadata;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1170,59 +942,22 @@ getJasmineRequireObj().Env = function(j$) {
|
|||||||
|
|
||||||
this.beforeEach = function(beforeEachFunction, timeout) {
|
this.beforeEach = function(beforeEachFunction, timeout) {
|
||||||
ensureIsNotNested('beforeEach');
|
ensureIsNotNested('beforeEach');
|
||||||
ensureIsFunctionOrAsync(beforeEachFunction, 'beforeEach');
|
suiteBuilder.beforeEach(beforeEachFunction, timeout);
|
||||||
|
|
||||||
if (timeout) {
|
|
||||||
j$.util.validateTimeout(timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
currentDeclarationSuite.beforeEach({
|
|
||||||
fn: beforeEachFunction,
|
|
||||||
timeout: timeout || 0
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.beforeAll = function(beforeAllFunction, timeout) {
|
this.beforeAll = function(beforeAllFunction, timeout) {
|
||||||
ensureIsNotNested('beforeAll');
|
ensureIsNotNested('beforeAll');
|
||||||
ensureIsFunctionOrAsync(beforeAllFunction, 'beforeAll');
|
suiteBuilder.beforeAll(beforeAllFunction, timeout);
|
||||||
|
|
||||||
if (timeout) {
|
|
||||||
j$.util.validateTimeout(timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
currentDeclarationSuite.beforeAll({
|
|
||||||
fn: beforeAllFunction,
|
|
||||||
timeout: timeout || 0
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.afterEach = function(afterEachFunction, timeout) {
|
this.afterEach = function(afterEachFunction, timeout) {
|
||||||
ensureIsNotNested('afterEach');
|
ensureIsNotNested('afterEach');
|
||||||
ensureIsFunctionOrAsync(afterEachFunction, 'afterEach');
|
suiteBuilder.afterEach(afterEachFunction, timeout);
|
||||||
|
|
||||||
if (timeout) {
|
|
||||||
j$.util.validateTimeout(timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
afterEachFunction.isCleanup = true;
|
|
||||||
currentDeclarationSuite.afterEach({
|
|
||||||
fn: afterEachFunction,
|
|
||||||
timeout: timeout || 0
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.afterAll = function(afterAllFunction, timeout) {
|
this.afterAll = function(afterAllFunction, timeout) {
|
||||||
ensureIsNotNested('afterAll');
|
ensureIsNotNested('afterAll');
|
||||||
ensureIsFunctionOrAsync(afterAllFunction, 'afterAll');
|
suiteBuilder.afterAll(afterAllFunction, timeout);
|
||||||
|
|
||||||
if (timeout) {
|
|
||||||
j$.util.validateTimeout(timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
currentDeclarationSuite.afterAll({
|
|
||||||
fn: afterAllFunction,
|
|
||||||
timeout: timeout || 0
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.pending = function(message) {
|
this.pending = function(message) {
|
||||||
|
|||||||
304
src/core/SuiteBuilder.js
Normal file
304
src/core/SuiteBuilder.js
Normal file
@@ -0,0 +1,304 @@
|
|||||||
|
getJasmineRequireObj().SuiteBuilder = function(j$) {
|
||||||
|
class SuiteBuilder {
|
||||||
|
constructor(options) {
|
||||||
|
this.env_ = options.env;
|
||||||
|
this.expectationFactory_ = options.expectationFactory;
|
||||||
|
this.suiteAsyncExpectationFactory_ = function(actual, suite) {
|
||||||
|
return options.asyncExpectationFactory(actual, suite, 'Suite');
|
||||||
|
};
|
||||||
|
this.specAsyncExpectationFactory_ = function(actual, suite) {
|
||||||
|
return options.asyncExpectationFactory(actual, suite, 'Spec');
|
||||||
|
};
|
||||||
|
this.onLateError_ = options.onLateError;
|
||||||
|
this.specResultCallback_ = options.specResultCallback;
|
||||||
|
this.specStarted_ = options.specStarted;
|
||||||
|
this.queueRunnerFactory_ = options.queueRunnerFactory;
|
||||||
|
|
||||||
|
this.nextSuiteId_ = 0;
|
||||||
|
this.nextSpecId_ = 0;
|
||||||
|
|
||||||
|
this.topSuite = this.suiteFactory_('Jasmine__TopLevel__Suite');
|
||||||
|
this.currentDeclarationSuite_ = this.topSuite;
|
||||||
|
this.totalSpecsDefined = 0;
|
||||||
|
this.focusedRunables = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
describe(description, definitionFn) {
|
||||||
|
ensureIsFunction(definitionFn, 'describe');
|
||||||
|
const suite = this.suiteFactory_(description);
|
||||||
|
if (definitionFn.length > 0) {
|
||||||
|
throw new Error('describe does not expect any arguments');
|
||||||
|
}
|
||||||
|
if (this.currentDeclarationSuite_.markedExcluding) {
|
||||||
|
suite.exclude();
|
||||||
|
}
|
||||||
|
this.addSpecsToSuite_(suite, definitionFn);
|
||||||
|
if (suite.parentSuite && !suite.children.length) {
|
||||||
|
throw new Error(
|
||||||
|
`describe with no children (describe() or it()): ${suite.getFullName()}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return suite;
|
||||||
|
}
|
||||||
|
|
||||||
|
fdescribe(description, definitionFn) {
|
||||||
|
ensureIsFunction(definitionFn, 'fdescribe');
|
||||||
|
const suite = this.suiteFactory_(description);
|
||||||
|
suite.isFocused = true;
|
||||||
|
|
||||||
|
this.focusedRunables.push(suite.id);
|
||||||
|
this.unfocusAncestor_();
|
||||||
|
this.addSpecsToSuite_(suite, definitionFn);
|
||||||
|
|
||||||
|
return suite;
|
||||||
|
}
|
||||||
|
|
||||||
|
xdescribe(description, definitionFn) {
|
||||||
|
ensureIsFunction(definitionFn, 'xdescribe');
|
||||||
|
const suite = this.suiteFactory_(description);
|
||||||
|
suite.exclude();
|
||||||
|
this.addSpecsToSuite_(suite, definitionFn);
|
||||||
|
|
||||||
|
return suite;
|
||||||
|
}
|
||||||
|
|
||||||
|
it(description, fn, timeout) {
|
||||||
|
// it() sometimes doesn't have a fn argument, so only check the type if
|
||||||
|
// it's given.
|
||||||
|
if (arguments.length > 1 && typeof fn !== 'undefined') {
|
||||||
|
ensureIsFunctionOrAsync(fn, 'it');
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.it_(description, fn, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
xit(description, fn, timeout) {
|
||||||
|
// xit(), like it(), doesn't always have a fn argument, so only check the
|
||||||
|
// type when needed.
|
||||||
|
if (arguments.length > 1 && typeof fn !== 'undefined') {
|
||||||
|
ensureIsFunctionOrAsync(fn, 'xit');
|
||||||
|
}
|
||||||
|
const spec = this.it_(description, fn, timeout);
|
||||||
|
spec.exclude('Temporarily disabled with xit');
|
||||||
|
return spec;
|
||||||
|
}
|
||||||
|
|
||||||
|
fit(description, fn, timeout) {
|
||||||
|
// Unlike it and xit, the function is required because it doesn't make
|
||||||
|
// sense to focus on nothing.
|
||||||
|
ensureIsFunctionOrAsync(fn, 'fit');
|
||||||
|
|
||||||
|
if (timeout) {
|
||||||
|
j$.util.validateTimeout(timeout);
|
||||||
|
}
|
||||||
|
const spec = this.specFactory_(description, fn, timeout);
|
||||||
|
this.currentDeclarationSuite_.addChild(spec);
|
||||||
|
this.focusedRunables.push(spec.id);
|
||||||
|
this.unfocusAncestor_();
|
||||||
|
return spec;
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(beforeEachFunction, timeout) {
|
||||||
|
ensureIsFunctionOrAsync(beforeEachFunction, 'beforeEach');
|
||||||
|
|
||||||
|
if (timeout) {
|
||||||
|
j$.util.validateTimeout(timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.currentDeclarationSuite_.beforeEach({
|
||||||
|
fn: beforeEachFunction,
|
||||||
|
timeout: timeout || 0
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeAll(beforeAllFunction, timeout) {
|
||||||
|
ensureIsFunctionOrAsync(beforeAllFunction, 'beforeAll');
|
||||||
|
|
||||||
|
if (timeout) {
|
||||||
|
j$.util.validateTimeout(timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.currentDeclarationSuite_.beforeAll({
|
||||||
|
fn: beforeAllFunction,
|
||||||
|
timeout: timeout || 0
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
afterEach(afterEachFunction, timeout) {
|
||||||
|
ensureIsFunctionOrAsync(afterEachFunction, 'afterEach');
|
||||||
|
|
||||||
|
if (timeout) {
|
||||||
|
j$.util.validateTimeout(timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
afterEachFunction.isCleanup = true;
|
||||||
|
this.currentDeclarationSuite_.afterEach({
|
||||||
|
fn: afterEachFunction,
|
||||||
|
timeout: timeout || 0
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
afterAll(afterAllFunction, timeout) {
|
||||||
|
ensureIsFunctionOrAsync(afterAllFunction, 'afterAll');
|
||||||
|
|
||||||
|
if (timeout) {
|
||||||
|
j$.util.validateTimeout(timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.currentDeclarationSuite_.afterAll({
|
||||||
|
fn: afterAllFunction,
|
||||||
|
timeout: timeout || 0
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
it_(description, fn, timeout) {
|
||||||
|
if (timeout) {
|
||||||
|
j$.util.validateTimeout(timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
const spec = this.specFactory_(description, fn, timeout);
|
||||||
|
if (this.currentDeclarationSuite_.markedExcluding) {
|
||||||
|
spec.exclude();
|
||||||
|
}
|
||||||
|
this.currentDeclarationSuite_.addChild(spec);
|
||||||
|
|
||||||
|
return spec;
|
||||||
|
}
|
||||||
|
|
||||||
|
suiteFactory_(description) {
|
||||||
|
const config = this.env_.configuration();
|
||||||
|
return new j$.Suite({
|
||||||
|
id: 'suite' + this.nextSuiteId_++,
|
||||||
|
description,
|
||||||
|
parentSuite: this.currentDeclarationSuite_,
|
||||||
|
timer: new j$.Timer(),
|
||||||
|
expectationFactory: this.expectationFactory_,
|
||||||
|
asyncExpectationFactory: this.suiteAsyncExpectationFactory_,
|
||||||
|
throwOnExpectationFailure: config.stopSpecOnExpectationFailure,
|
||||||
|
autoCleanClosures: config.autoCleanClosures,
|
||||||
|
onLateError: this.onLateError_
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
addSpecsToSuite_(suite, definitionFn) {
|
||||||
|
const parentSuite = this.currentDeclarationSuite_;
|
||||||
|
parentSuite.addChild(suite);
|
||||||
|
this.currentDeclarationSuite_ = suite;
|
||||||
|
|
||||||
|
try {
|
||||||
|
definitionFn();
|
||||||
|
} catch (e) {
|
||||||
|
suite.handleException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.currentDeclarationSuite_ = parentSuite;
|
||||||
|
}
|
||||||
|
|
||||||
|
specFactory_(description, fn, timeout) {
|
||||||
|
this.totalSpecsDefined++;
|
||||||
|
const config = this.env_.configuration();
|
||||||
|
const suite = this.currentDeclarationSuite_;
|
||||||
|
const spec = new j$.Spec({
|
||||||
|
id: 'spec' + this.nextSpecId_++,
|
||||||
|
beforeAndAfterFns: beforeAndAfterFns(suite),
|
||||||
|
expectationFactory: this.expectationFactory_,
|
||||||
|
asyncExpectationFactory: this.specAsyncExpectationFactory_,
|
||||||
|
onLateError: this.onLateError_,
|
||||||
|
resultCallback: (result, next) => {
|
||||||
|
this.specResultCallback_(spec, result, next);
|
||||||
|
},
|
||||||
|
getSpecName: function(spec) {
|
||||||
|
return getSpecName(spec, suite);
|
||||||
|
},
|
||||||
|
onStart: (spec, next) => this.specStarted_(spec, suite, next),
|
||||||
|
description: description,
|
||||||
|
queueRunnerFactory: this.queueRunnerFactory_,
|
||||||
|
userContext: function() {
|
||||||
|
return suite.clonedSharedUserContext();
|
||||||
|
},
|
||||||
|
queueableFn: {
|
||||||
|
fn: fn,
|
||||||
|
timeout: timeout || 0
|
||||||
|
},
|
||||||
|
throwOnExpectationFailure: config.stopSpecOnExpectationFailure,
|
||||||
|
autoCleanClosures: config.autoCleanClosures,
|
||||||
|
timer: new j$.Timer()
|
||||||
|
});
|
||||||
|
return spec;
|
||||||
|
}
|
||||||
|
|
||||||
|
unfocusAncestor_() {
|
||||||
|
const focusedAncestor = findFocusedAncestor(
|
||||||
|
this.currentDeclarationSuite_
|
||||||
|
);
|
||||||
|
|
||||||
|
if (focusedAncestor) {
|
||||||
|
for (let i = 0; i < this.focusedRunables.length; i++) {
|
||||||
|
if (this.focusedRunables[i] === focusedAncestor) {
|
||||||
|
this.focusedRunables.splice(i, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function findFocusedAncestor(suite) {
|
||||||
|
while (suite) {
|
||||||
|
if (suite.isFocused) {
|
||||||
|
return suite.id;
|
||||||
|
}
|
||||||
|
suite = suite.parentSuite;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function ensureIsFunction(fn, caller) {
|
||||||
|
if (!j$.isFunction_(fn)) {
|
||||||
|
throw new Error(
|
||||||
|
caller + ' expects a function argument; received ' + j$.getType_(fn)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function ensureIsFunctionOrAsync(fn, caller) {
|
||||||
|
if (!j$.isFunction_(fn) && !j$.isAsyncFunction_(fn)) {
|
||||||
|
throw new Error(
|
||||||
|
caller + ' expects a function argument; received ' + j$.getType_(fn)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function beforeAndAfterFns(targetSuite) {
|
||||||
|
return function() {
|
||||||
|
let befores = [],
|
||||||
|
afters = [],
|
||||||
|
suite = targetSuite;
|
||||||
|
|
||||||
|
while (suite) {
|
||||||
|
befores = befores.concat(suite.beforeFns);
|
||||||
|
afters = afters.concat(suite.afterFns);
|
||||||
|
|
||||||
|
suite = suite.parentSuite;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
befores: befores.reverse(),
|
||||||
|
afters: afters
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSpecName(spec, suite) {
|
||||||
|
const fullName = [spec.description],
|
||||||
|
suiteFullName = suite.getFullName();
|
||||||
|
|
||||||
|
if (suiteFullName !== '') {
|
||||||
|
fullName.unshift(suiteFullName);
|
||||||
|
}
|
||||||
|
return fullName.join(' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
return SuiteBuilder;
|
||||||
|
};
|
||||||
@@ -78,6 +78,7 @@ var getJasmineRequireObj = (function(jasmineGlobal) {
|
|||||||
j$.StringContaining = jRequire.StringContaining(j$);
|
j$.StringContaining = jRequire.StringContaining(j$);
|
||||||
j$.UserContext = jRequire.UserContext(j$);
|
j$.UserContext = jRequire.UserContext(j$);
|
||||||
j$.Suite = jRequire.Suite(j$);
|
j$.Suite = jRequire.Suite(j$);
|
||||||
|
j$.SuiteBuilder = jRequire.SuiteBuilder(j$);
|
||||||
j$.Timer = jRequire.Timer();
|
j$.Timer = jRequire.Timer();
|
||||||
j$.TreeProcessor = jRequire.TreeProcessor();
|
j$.TreeProcessor = jRequire.TreeProcessor();
|
||||||
j$.version = jRequire.version();
|
j$.version = jRequire.version();
|
||||||
|
|||||||
Reference in New Issue
Block a user