Support running jasmine multiple times
Add support for running jasmine multiple times.
```js
const Jasmine = require('jasmine');
async function main() {
const jasmine = new Jasmine({ projectBaseDir: process.cwd() });
let specId = 'spec0';
jasmine.loadConfigFile('./spec/support/jasmine.json');
jasmine.env.configure({
specFilter(sp) {
return sp.id === specId;
},
autoCleanClosures: false
});
jasmine.exit = () => {};
await jasmine.execute();
specId = 'spec2';
await jasmine.execute();
}
main().catch((err) => {
console.error(err);
process.exitCode = 1;
});
```
With `jasmine.env.configure({ autoCleanClosures: false })` you disable Jasmine's feature to automatically clean closures (functions) during the test run. This is a requirement to be able to rerun.
When `execute` is called more than once, the `topSuite.reset` is called, which will reset the state for the next run as well as reset any child suites.
Add a function `exclude` to the `Suite` and `Spec` clases. This functions similar to `pend`, but will allow the "pending" state to persist over multiple runs. This is useful when `xit` is used.
Revert changes to jasmine.js
fix: make sure to call hooks during second run
Remove jsdoc from private apis
Fix elint issue
Add new line
This commit is contained in:
@@ -265,13 +265,13 @@ describe('Env', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('#xit', function() {
|
describe('#xit', function() {
|
||||||
it('calls spec.pend with "Temporarily disabled with xit"', function() {
|
it('calls spec.exclude with "Temporarily disabled with xit"', function() {
|
||||||
var pendSpy = jasmine.createSpy();
|
var excludeSpy = jasmine.createSpy();
|
||||||
spyOn(env, 'it').and.returnValue({
|
spyOn(env, 'it').and.returnValue({
|
||||||
pend: pendSpy
|
exclude: excludeSpy
|
||||||
});
|
});
|
||||||
env.xit('foo', function() {});
|
env.xit('foo', function() {});
|
||||||
expect(pendSpy).toHaveBeenCalledWith('Temporarily disabled with xit');
|
expect(excludeSpy).toHaveBeenCalledWith('Temporarily disabled with xit');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('throws an error when it receives a non-fn argument', function() {
|
it('throws an error when it receives a non-fn argument', function() {
|
||||||
@@ -521,5 +521,18 @@ describe('Env', function() {
|
|||||||
jasmine.getEnv().requireNoPromises();
|
jasmine.getEnv().requireNoPromises();
|
||||||
expect(env.execute()).toBeUndefined();
|
expect(env.execute()).toBeUndefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should reset the topSuite when run twice', function() {
|
||||||
|
jasmine.getEnv().requirePromises();
|
||||||
|
spyOn(env.topSuite(), 'reset');
|
||||||
|
return env
|
||||||
|
.execute() // 1
|
||||||
|
.then(function() {
|
||||||
|
return env.execute(); // 2
|
||||||
|
})
|
||||||
|
.then(function() {
|
||||||
|
expect(env.topSuite().reset).toHaveBeenCalledOnceWith();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -142,4 +142,86 @@ describe('Suite', function() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('attr.autoCleanClosures', function() {
|
||||||
|
function arrangeSuite(attrs) {
|
||||||
|
var suite = new jasmineUnderTest.Suite(attrs);
|
||||||
|
suite.beforeAll(function() {});
|
||||||
|
suite.beforeEach(function() {});
|
||||||
|
suite.afterEach(function() {});
|
||||||
|
suite.afterAll(function() {});
|
||||||
|
return suite;
|
||||||
|
}
|
||||||
|
|
||||||
|
it('should clean closures when "attr.autoCleanClosures" is missing', function() {
|
||||||
|
var suite = arrangeSuite({});
|
||||||
|
suite.cleanupBeforeAfter();
|
||||||
|
expect(suite.beforeAllFns[0].fn).toBe(null);
|
||||||
|
expect(suite.beforeFns[0].fn).toBe(null);
|
||||||
|
expect(suite.afterFns[0].fn).toBe(null);
|
||||||
|
expect(suite.afterAllFns[0].fn).toBe(null);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should clean closures when "attr.autoCleanClosures" is true', function() {
|
||||||
|
var suite = arrangeSuite({ autoCleanClosures: true });
|
||||||
|
suite.cleanupBeforeAfter();
|
||||||
|
expect(suite.beforeAllFns[0].fn).toBe(null);
|
||||||
|
expect(suite.beforeFns[0].fn).toBe(null);
|
||||||
|
expect(suite.afterFns[0].fn).toBe(null);
|
||||||
|
expect(suite.afterAllFns[0].fn).toBe(null);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should NOT clean closures when "attr.autoCleanClosures" is false', function() {
|
||||||
|
var suite = arrangeSuite({ autoCleanClosures: false });
|
||||||
|
suite.cleanupBeforeAfter();
|
||||||
|
expect(suite.beforeAllFns[0].fn).not.toBe(null);
|
||||||
|
expect(suite.beforeFns[0].fn).not.toBe(null);
|
||||||
|
expect(suite.afterFns[0].fn).not.toBe(null);
|
||||||
|
expect(suite.afterAllFns[0].fn).not.toBe(null);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#reset', function() {
|
||||||
|
it('should reset the "pending" status', function() {
|
||||||
|
var suite = new jasmineUnderTest.Suite({});
|
||||||
|
suite.pend();
|
||||||
|
suite.reset();
|
||||||
|
expect(suite.getResult().status).toBe('passed');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not reset the "pending" status when the suite was excluded', function() {
|
||||||
|
var suite = new jasmineUnderTest.Suite({});
|
||||||
|
suite.exclude();
|
||||||
|
suite.reset();
|
||||||
|
expect(suite.getResult().status).toBe('pending');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should also reset the children', function() {
|
||||||
|
var suite = new jasmineUnderTest.Suite({});
|
||||||
|
var child1 = jasmine.createSpyObj(['reset']);
|
||||||
|
var child2 = jasmine.createSpyObj(['reset']);
|
||||||
|
suite.addChild(child1);
|
||||||
|
suite.addChild(child2);
|
||||||
|
|
||||||
|
suite.reset();
|
||||||
|
|
||||||
|
expect(child1.reset).toHaveBeenCalled();
|
||||||
|
expect(child2.reset).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should reset the failedExpectations', function() {
|
||||||
|
var suite = new jasmineUnderTest.Suite({
|
||||||
|
expectationResultFactory: function(error) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
suite.onException(new Error());
|
||||||
|
|
||||||
|
suite.reset();
|
||||||
|
|
||||||
|
var result = suite.getResult();
|
||||||
|
expect(result.status).toBe('passed');
|
||||||
|
expect(result.failedExpectations).toHaveSize(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1026,4 +1026,209 @@ describe('spec running', function() {
|
|||||||
env.stopOnSpecFailure(true);
|
env.stopOnSpecFailure(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('run multiple times', function() {
|
||||||
|
beforeEach(function() {
|
||||||
|
env.configure({ autoCleanClosures: false, random: false });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be able to run multiple times', function() {
|
||||||
|
var actions = [];
|
||||||
|
|
||||||
|
env.describe('Suite', function() {
|
||||||
|
env.it('spec1', function() {
|
||||||
|
actions.push('spec1');
|
||||||
|
});
|
||||||
|
env.describe('inner suite', function() {
|
||||||
|
env.it('spec2', function() {
|
||||||
|
actions.push('spec2');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return env.execute().then(function() {
|
||||||
|
expect(actions).toEqual(['spec1', 'spec2']);
|
||||||
|
return env.execute().then(function() {
|
||||||
|
expect(actions).toEqual(['spec1', 'spec2', 'spec1', 'spec2']);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should reset results between runs', function() {
|
||||||
|
var specResults = {};
|
||||||
|
var suiteResults = {};
|
||||||
|
var firstExecution = true;
|
||||||
|
|
||||||
|
env.addReporter({
|
||||||
|
specDone: function(spec) {
|
||||||
|
specResults[spec.description] = spec.status;
|
||||||
|
},
|
||||||
|
suiteDone: function(suite) {
|
||||||
|
suiteResults[suite.description] = suite.status;
|
||||||
|
},
|
||||||
|
jasmineDone: function() {
|
||||||
|
firstExecution = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
env.describe('suite0', function() {
|
||||||
|
env.it('spec1', function() {
|
||||||
|
if (firstExecution) {
|
||||||
|
env.expect(1).toBe(2);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
env.describe('suite1', function() {
|
||||||
|
env.it('spec2', function() {
|
||||||
|
if (firstExecution) {
|
||||||
|
env.pending();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
env.xit('spec3', function() {}); // Always pending
|
||||||
|
});
|
||||||
|
env.describe('suite2', function() {
|
||||||
|
env.it('spec4', function() {
|
||||||
|
if (firstExecution) {
|
||||||
|
throw new Error('spec 3 fails');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
env.describe('suite3', function() {
|
||||||
|
beforeEach(function() {
|
||||||
|
throw new Error('suite 3 fails');
|
||||||
|
});
|
||||||
|
env.it('spec5', function() {});
|
||||||
|
});
|
||||||
|
env.xdescribe('suite4', function() {
|
||||||
|
// Always pending
|
||||||
|
env.it('spec6', function() {});
|
||||||
|
});
|
||||||
|
env.describe('suite5', function() {
|
||||||
|
env.it('spec7');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return env.execute().then(function() {
|
||||||
|
expect(specResults).toEqual({
|
||||||
|
spec1: 'failed',
|
||||||
|
spec2: 'pending',
|
||||||
|
spec3: 'pending',
|
||||||
|
spec4: 'failed',
|
||||||
|
spec6: 'pending',
|
||||||
|
spec7: 'pending'
|
||||||
|
});
|
||||||
|
expect(suiteResults).toEqual({
|
||||||
|
suite0: 'passed',
|
||||||
|
suite1: 'passed',
|
||||||
|
suite2: 'passed',
|
||||||
|
suite3: 'failed',
|
||||||
|
suite4: 'pending',
|
||||||
|
suite5: 'passed'
|
||||||
|
});
|
||||||
|
return env.execute().then(function() {
|
||||||
|
expect(specResults).toEqual({
|
||||||
|
spec1: 'passed',
|
||||||
|
spec2: 'passed',
|
||||||
|
spec3: 'pending',
|
||||||
|
spec4: 'passed',
|
||||||
|
spec6: 'pending',
|
||||||
|
spec7: 'pending'
|
||||||
|
});
|
||||||
|
expect(suiteResults).toEqual({
|
||||||
|
suite0: 'passed',
|
||||||
|
suite1: 'passed',
|
||||||
|
suite2: 'passed',
|
||||||
|
suite3: 'passed',
|
||||||
|
suite4: 'pending',
|
||||||
|
suite5: 'passed'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should execute before and after hooks per run', function() {
|
||||||
|
var timeline = [];
|
||||||
|
var timelineFn = function(hookName) {
|
||||||
|
return function() {
|
||||||
|
timeline.push(hookName);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
var expectedTimeLine = [
|
||||||
|
'beforeAll',
|
||||||
|
'beforeEach',
|
||||||
|
'spec1',
|
||||||
|
'afterEach',
|
||||||
|
'beforeEach',
|
||||||
|
'spec2',
|
||||||
|
'afterEach',
|
||||||
|
'afterAll'
|
||||||
|
];
|
||||||
|
|
||||||
|
env.describe('suite0', function() {
|
||||||
|
env.beforeAll(timelineFn('beforeAll'));
|
||||||
|
env.beforeEach(timelineFn('beforeEach'));
|
||||||
|
env.afterEach(timelineFn('afterEach'));
|
||||||
|
env.afterAll(timelineFn('afterAll'));
|
||||||
|
env.it('spec1', timelineFn('spec1'));
|
||||||
|
env.it('spec2', timelineFn('spec2'));
|
||||||
|
});
|
||||||
|
return env.execute().then(function() {
|
||||||
|
expect(timeline).toEqual(expectedTimeLine);
|
||||||
|
timeline = [];
|
||||||
|
return env.execute().then(function() {
|
||||||
|
expect(timeline).toEqual(expectedTimeLine);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be able to filter out different tests in subsequent runs', function() {
|
||||||
|
var specResults = {};
|
||||||
|
var focussedSpec = 'spec1';
|
||||||
|
|
||||||
|
env.configure({
|
||||||
|
specFilter: function(spec) {
|
||||||
|
return spec.description === focussedSpec;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
env.addReporter({
|
||||||
|
specDone: function(spec) {
|
||||||
|
specResults[spec.description] = spec.status;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
env.describe('suite0', function() {
|
||||||
|
env.it('spec1', function() {});
|
||||||
|
env.it('spec2', function() {});
|
||||||
|
env.it('spec3', function() {});
|
||||||
|
});
|
||||||
|
|
||||||
|
return env
|
||||||
|
.execute()
|
||||||
|
.then(function() {
|
||||||
|
expect(specResults).toEqual({
|
||||||
|
spec1: 'passed',
|
||||||
|
spec2: 'excluded',
|
||||||
|
spec3: 'excluded'
|
||||||
|
});
|
||||||
|
focussedSpec = 'spec2';
|
||||||
|
return env.execute();
|
||||||
|
})
|
||||||
|
.then(function() {
|
||||||
|
expect(specResults).toEqual({
|
||||||
|
spec1: 'excluded',
|
||||||
|
spec2: 'passed',
|
||||||
|
spec3: 'excluded'
|
||||||
|
});
|
||||||
|
focussedSpec = 'spec3';
|
||||||
|
return env.execute();
|
||||||
|
})
|
||||||
|
.then(function() {
|
||||||
|
expect(specResults).toEqual({
|
||||||
|
spec1: 'excluded',
|
||||||
|
spec2: 'excluded',
|
||||||
|
spec3: 'passed'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -138,7 +138,16 @@ getJasmineRequireObj().Env = function(j$) {
|
|||||||
* @type function
|
* @type function
|
||||||
* @default undefined
|
* @default undefined
|
||||||
*/
|
*/
|
||||||
Promise: undefined
|
Promise: undefined,
|
||||||
|
/**
|
||||||
|
* Clean closures when a suite is done running (done by clearing the stored function reference).
|
||||||
|
* This prevents memory leaks, but you won't be able to run jasmine multiple times.
|
||||||
|
* @name Configuration#autoCleanClosures
|
||||||
|
* @since 3.10.0
|
||||||
|
* @type boolean
|
||||||
|
* @default true
|
||||||
|
*/
|
||||||
|
autoCleanClosures: true
|
||||||
};
|
};
|
||||||
|
|
||||||
var currentSuite = function() {
|
var currentSuite = function() {
|
||||||
@@ -191,7 +200,8 @@ getJasmineRequireObj().Env = function(j$) {
|
|||||||
var booleanProps = [
|
var booleanProps = [
|
||||||
'random',
|
'random',
|
||||||
'failSpecWithNoExpectations',
|
'failSpecWithNoExpectations',
|
||||||
'hideDisabled'
|
'hideDisabled',
|
||||||
|
'autoCleanClosures'
|
||||||
];
|
];
|
||||||
|
|
||||||
booleanProps.forEach(function(prop) {
|
booleanProps.forEach(function(prop) {
|
||||||
@@ -497,10 +507,11 @@ getJasmineRequireObj().Env = function(j$) {
|
|||||||
delete runnableResources[id];
|
delete runnableResources[id];
|
||||||
};
|
};
|
||||||
|
|
||||||
var beforeAndAfterFns = function(suite) {
|
var beforeAndAfterFns = function(targetSuite) {
|
||||||
return function() {
|
return function() {
|
||||||
var befores = [],
|
var befores = [],
|
||||||
afters = [];
|
afters = [],
|
||||||
|
suite = targetSuite;
|
||||||
|
|
||||||
while (suite) {
|
while (suite) {
|
||||||
befores = befores.concat(suite.beforeFns);
|
befores = befores.concat(suite.beforeFns);
|
||||||
@@ -701,9 +712,9 @@ getJasmineRequireObj().Env = function(j$) {
|
|||||||
description: 'Jasmine__TopLevel__Suite',
|
description: 'Jasmine__TopLevel__Suite',
|
||||||
expectationFactory: expectationFactory,
|
expectationFactory: expectationFactory,
|
||||||
asyncExpectationFactory: suiteAsyncExpectationFactory,
|
asyncExpectationFactory: suiteAsyncExpectationFactory,
|
||||||
expectationResultFactory: expectationResultFactory
|
expectationResultFactory: expectationResultFactory,
|
||||||
|
autoCleanClosures: config.autoCleanClosures
|
||||||
});
|
});
|
||||||
defaultResourcesForRunnable(topSuite.id);
|
|
||||||
currentDeclarationSuite = topSuite;
|
currentDeclarationSuite = topSuite;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -821,6 +832,11 @@ getJasmineRequireObj().Env = function(j$) {
|
|||||||
* @return {Promise<undefined>}
|
* @return {Promise<undefined>}
|
||||||
*/
|
*/
|
||||||
this.execute = function(runnablesToRun, onComplete) {
|
this.execute = function(runnablesToRun, onComplete) {
|
||||||
|
if (this._executedBefore) {
|
||||||
|
topSuite.reset();
|
||||||
|
}
|
||||||
|
this._executedBefore = true;
|
||||||
|
defaultResourcesForRunnable(topSuite.id);
|
||||||
installGlobalErrors();
|
installGlobalErrors();
|
||||||
|
|
||||||
if (!runnablesToRun) {
|
if (!runnablesToRun) {
|
||||||
@@ -1107,7 +1123,8 @@ getJasmineRequireObj().Env = function(j$) {
|
|||||||
expectationFactory: expectationFactory,
|
expectationFactory: expectationFactory,
|
||||||
asyncExpectationFactory: suiteAsyncExpectationFactory,
|
asyncExpectationFactory: suiteAsyncExpectationFactory,
|
||||||
expectationResultFactory: expectationResultFactory,
|
expectationResultFactory: expectationResultFactory,
|
||||||
throwOnExpectationFailure: config.oneFailurePerSpec
|
throwOnExpectationFailure: config.oneFailurePerSpec,
|
||||||
|
autoCleanClosures: config.autoCleanClosures
|
||||||
});
|
});
|
||||||
|
|
||||||
return suite;
|
return suite;
|
||||||
@@ -1120,8 +1137,8 @@ getJasmineRequireObj().Env = function(j$) {
|
|||||||
if (specDefinitions.length > 0) {
|
if (specDefinitions.length > 0) {
|
||||||
throw new Error('describe does not expect any arguments');
|
throw new Error('describe does not expect any arguments');
|
||||||
}
|
}
|
||||||
if (currentDeclarationSuite.markedPending) {
|
if (currentDeclarationSuite.markedExcluding) {
|
||||||
suite.pend();
|
suite.exclude();
|
||||||
}
|
}
|
||||||
addSpecsToSuite(suite, specDefinitions);
|
addSpecsToSuite(suite, specDefinitions);
|
||||||
return suite;
|
return suite;
|
||||||
@@ -1131,7 +1148,7 @@ getJasmineRequireObj().Env = function(j$) {
|
|||||||
ensureIsNotNested('xdescribe');
|
ensureIsNotNested('xdescribe');
|
||||||
ensureIsFunction(specDefinitions, 'xdescribe');
|
ensureIsFunction(specDefinitions, 'xdescribe');
|
||||||
var suite = suiteFactory(description);
|
var suite = suiteFactory(description);
|
||||||
suite.pend();
|
suite.exclude();
|
||||||
addSpecsToSuite(suite, specDefinitions);
|
addSpecsToSuite(suite, specDefinitions);
|
||||||
return suite;
|
return suite;
|
||||||
};
|
};
|
||||||
@@ -1216,6 +1233,7 @@ getJasmineRequireObj().Env = function(j$) {
|
|||||||
timeout: timeout || 0
|
timeout: timeout || 0
|
||||||
},
|
},
|
||||||
throwOnExpectationFailure: config.oneFailurePerSpec,
|
throwOnExpectationFailure: config.oneFailurePerSpec,
|
||||||
|
autoCleanClosures: config.autoCleanClosures,
|
||||||
timer: new j$.Timer()
|
timer: new j$.Timer()
|
||||||
});
|
});
|
||||||
return spec;
|
return spec;
|
||||||
@@ -1251,8 +1269,8 @@ getJasmineRequireObj().Env = function(j$) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var spec = specFactory(description, fn, currentDeclarationSuite, timeout);
|
var spec = specFactory(description, fn, currentDeclarationSuite, timeout);
|
||||||
if (currentDeclarationSuite.markedPending) {
|
if (currentDeclarationSuite.markedExcluding) {
|
||||||
spec.pend();
|
spec.exclude();
|
||||||
}
|
}
|
||||||
currentDeclarationSuite.addChild(spec);
|
currentDeclarationSuite.addChild(spec);
|
||||||
return spec;
|
return spec;
|
||||||
@@ -1266,7 +1284,7 @@ getJasmineRequireObj().Env = function(j$) {
|
|||||||
ensureIsFunctionOrAsync(fn, 'xit');
|
ensureIsFunctionOrAsync(fn, 'xit');
|
||||||
}
|
}
|
||||||
var spec = this.it.apply(this, arguments);
|
var spec = this.it.apply(this, arguments);
|
||||||
spec.pend('Temporarily disabled with xit');
|
spec.exclude('Temporarily disabled with xit');
|
||||||
return spec;
|
return spec;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,8 @@ getJasmineRequireObj().Spec = function(j$) {
|
|||||||
return {};
|
return {};
|
||||||
};
|
};
|
||||||
this.onStart = attrs.onStart || function() {};
|
this.onStart = attrs.onStart || function() {};
|
||||||
|
this.autoCleanClosures =
|
||||||
|
attrs.autoCleanClosures === undefined ? true : !!attrs.autoCleanClosures;
|
||||||
this.getSpecName =
|
this.getSpecName =
|
||||||
attrs.getSpecName ||
|
attrs.getSpecName ||
|
||||||
function() {
|
function() {
|
||||||
@@ -53,7 +55,7 @@ getJasmineRequireObj().Spec = function(j$) {
|
|||||||
this.timer = attrs.timer || new j$.Timer();
|
this.timer = attrs.timer || new j$.Timer();
|
||||||
|
|
||||||
if (!this.queueableFn.fn) {
|
if (!this.queueableFn.fn) {
|
||||||
this.pend();
|
this.exclude();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -121,7 +123,9 @@ x */
|
|||||||
|
|
||||||
var complete = {
|
var complete = {
|
||||||
fn: function(done) {
|
fn: function(done) {
|
||||||
self.queueableFn.fn = null;
|
if (self.autoCleanClosures) {
|
||||||
|
self.queueableFn.fn = null;
|
||||||
|
}
|
||||||
self.result.status = self.status(excluded, failSpecWithNoExp);
|
self.result.status = self.status(excluded, failSpecWithNoExp);
|
||||||
self.result.duration = self.timer.elapsed();
|
self.result.duration = self.timer.elapsed();
|
||||||
self.resultCallback(self.result, done);
|
self.resultCallback(self.result, done);
|
||||||
@@ -158,6 +162,37 @@ x */
|
|||||||
this.queueRunnerFactory(runnerConfig);
|
this.queueRunnerFactory(runnerConfig);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Spec.prototype.reset = function() {
|
||||||
|
/**
|
||||||
|
* @typedef SpecResult
|
||||||
|
* @property {Int} id - The unique id of this spec.
|
||||||
|
* @property {String} description - The description passed to the {@link it} that created this spec.
|
||||||
|
* @property {String} fullName - The full description including all ancestors of this spec.
|
||||||
|
* @property {Expectation[]} failedExpectations - The list of expectations that failed during execution of this spec.
|
||||||
|
* @property {Expectation[]} passedExpectations - The list of expectations that passed during execution of this spec.
|
||||||
|
* @property {Expectation[]} deprecationWarnings - The list of deprecation warnings that occurred during execution this spec.
|
||||||
|
* @property {String} pendingReason - If the spec is {@link pending}, this will be the reason.
|
||||||
|
* @property {String} status - Once the spec has completed, this string represents the pass/fail status of this spec.
|
||||||
|
* @property {number} duration - The time in ms used by the spec execution, including any before/afterEach.
|
||||||
|
* @property {Object} properties - User-supplied properties, if any, that were set using {@link Env#setSpecProperty}
|
||||||
|
* @property {TraceEntry[]|null} trace - Trace messages, if any, that were logged using {@link Env#trace} during a failing spec.
|
||||||
|
* @since 2.0.0
|
||||||
|
*/
|
||||||
|
this.result = {
|
||||||
|
id: this.id,
|
||||||
|
description: this.description,
|
||||||
|
fullName: this.getFullName(),
|
||||||
|
failedExpectations: [],
|
||||||
|
passedExpectations: [],
|
||||||
|
deprecationWarnings: [],
|
||||||
|
pendingReason: this.excludeMessage,
|
||||||
|
duration: null,
|
||||||
|
properties: null,
|
||||||
|
trace: null
|
||||||
|
};
|
||||||
|
this.markedPending = this.markedExcluding;
|
||||||
|
};
|
||||||
|
|
||||||
Spec.prototype.onException = function onException(e) {
|
Spec.prototype.onException = function onException(e) {
|
||||||
if (Spec.isPendingSpecException(e)) {
|
if (Spec.isPendingSpecException(e)) {
|
||||||
this.pend(extractCustomPendingMessage(e));
|
this.pend(extractCustomPendingMessage(e));
|
||||||
@@ -181,6 +216,10 @@ x */
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Marks state as pending
|
||||||
|
* @param {string} [message] An optional reason message
|
||||||
|
*/
|
||||||
Spec.prototype.pend = function(message) {
|
Spec.prototype.pend = function(message) {
|
||||||
this.markedPending = true;
|
this.markedPending = true;
|
||||||
if (message) {
|
if (message) {
|
||||||
@@ -188,6 +227,19 @@ x */
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Like {@link Spec#pend}, but pending state will survive {@link Spec#reset}
|
||||||
|
* Useful for fit, xit, where pending state remains.
|
||||||
|
* @param {string} [message] An optional reason message
|
||||||
|
*/
|
||||||
|
Spec.prototype.exclude = function(message) {
|
||||||
|
this.markedExcluding = true;
|
||||||
|
if (this.message) {
|
||||||
|
this.excludeMessage = message;
|
||||||
|
}
|
||||||
|
this.pend();
|
||||||
|
};
|
||||||
|
|
||||||
Spec.prototype.getResult = function() {
|
Spec.prototype.getResult = function() {
|
||||||
this.result.status = this.status();
|
this.result.status = this.status();
|
||||||
return this.result;
|
return this.result;
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ getJasmineRequireObj().Suite = function(j$) {
|
|||||||
this.asyncExpectationFactory = attrs.asyncExpectationFactory;
|
this.asyncExpectationFactory = attrs.asyncExpectationFactory;
|
||||||
this.expectationResultFactory = attrs.expectationResultFactory;
|
this.expectationResultFactory = attrs.expectationResultFactory;
|
||||||
this.throwOnExpectationFailure = !!attrs.throwOnExpectationFailure;
|
this.throwOnExpectationFailure = !!attrs.throwOnExpectationFailure;
|
||||||
|
this.autoCleanClosures =
|
||||||
|
attrs.autoCleanClosures === undefined ? true : !!attrs.autoCleanClosures;
|
||||||
|
|
||||||
this.beforeFns = [];
|
this.beforeFns = [];
|
||||||
this.afterFns = [];
|
this.afterFns = [];
|
||||||
@@ -49,27 +51,7 @@ getJasmineRequireObj().Suite = function(j$) {
|
|||||||
*/
|
*/
|
||||||
this.children = [];
|
this.children = [];
|
||||||
|
|
||||||
/**
|
this.reset();
|
||||||
* @typedef SuiteResult
|
|
||||||
* @property {Int} id - The unique id of this suite.
|
|
||||||
* @property {String} description - The description text passed to the {@link describe} that made this suite.
|
|
||||||
* @property {String} fullName - The full description including all ancestors of this suite.
|
|
||||||
* @property {Expectation[]} failedExpectations - The list of expectations that failed in an {@link afterAll} for this suite.
|
|
||||||
* @property {Expectation[]} deprecationWarnings - The list of deprecation warnings that occurred on this suite.
|
|
||||||
* @property {String} status - Once the suite has completed, this string represents the pass/fail status of this suite.
|
|
||||||
* @property {number} duration - The time in ms for Suite execution, including any before/afterAll, before/afterEach.
|
|
||||||
* @property {Object} properties - User-supplied properties, if any, that were set using {@link Env#setSuiteProperty}
|
|
||||||
* @since 2.0.0
|
|
||||||
*/
|
|
||||||
this.result = {
|
|
||||||
id: this.id,
|
|
||||||
description: this.description,
|
|
||||||
fullName: this.getFullName(),
|
|
||||||
failedExpectations: [],
|
|
||||||
deprecationWarnings: [],
|
|
||||||
duration: null,
|
|
||||||
properties: null
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Suite.prototype.setSuiteProperty = function(key, value) {
|
Suite.prototype.setSuiteProperty = function(key, value) {
|
||||||
@@ -106,10 +88,22 @@ getJasmineRequireObj().Suite = function(j$) {
|
|||||||
return fullName.join(' ');
|
return fullName.join(' ');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Mark the suite with "pending" status
|
||||||
|
*/
|
||||||
Suite.prototype.pend = function() {
|
Suite.prototype.pend = function() {
|
||||||
this.markedPending = true;
|
this.markedPending = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Like {@link Suite#pend}, but pending state will survive {@link Spec#reset}
|
||||||
|
* Useful for fdescribe, xdescribe, where pending state should remain.
|
||||||
|
*/
|
||||||
|
Suite.prototype.exclude = function() {
|
||||||
|
this.pend();
|
||||||
|
this.markedExcluding = true;
|
||||||
|
};
|
||||||
|
|
||||||
Suite.prototype.beforeEach = function(fn) {
|
Suite.prototype.beforeEach = function(fn) {
|
||||||
this.beforeFns.unshift(fn);
|
this.beforeFns.unshift(fn);
|
||||||
};
|
};
|
||||||
@@ -141,10 +135,40 @@ getJasmineRequireObj().Suite = function(j$) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Suite.prototype.cleanupBeforeAfter = function() {
|
Suite.prototype.cleanupBeforeAfter = function() {
|
||||||
removeFns(this.beforeAllFns);
|
if (this.autoCleanClosures) {
|
||||||
removeFns(this.afterAllFns);
|
removeFns(this.beforeAllFns);
|
||||||
removeFns(this.beforeFns);
|
removeFns(this.afterAllFns);
|
||||||
removeFns(this.afterFns);
|
removeFns(this.beforeFns);
|
||||||
|
removeFns(this.afterFns);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Suite.prototype.reset = function() {
|
||||||
|
/**
|
||||||
|
* @typedef SuiteResult
|
||||||
|
* @property {Int} id - The unique id of this suite.
|
||||||
|
* @property {String} description - The description text passed to the {@link describe} that made this suite.
|
||||||
|
* @property {String} fullName - The full description including all ancestors of this suite.
|
||||||
|
* @property {Expectation[]} failedExpectations - The list of expectations that failed in an {@link afterAll} for this suite.
|
||||||
|
* @property {Expectation[]} deprecationWarnings - The list of deprecation warnings that occurred on this suite.
|
||||||
|
* @property {String} status - Once the suite has completed, this string represents the pass/fail status of this suite.
|
||||||
|
* @property {number} duration - The time in ms for Suite execution, including any before/afterAll, before/afterEach.
|
||||||
|
* @property {Object} properties - User-supplied properties, if any, that were set using {@link Env#setSuiteProperty}
|
||||||
|
* @since 2.0.0
|
||||||
|
*/
|
||||||
|
this.result = {
|
||||||
|
id: this.id,
|
||||||
|
description: this.description,
|
||||||
|
fullName: this.getFullName(),
|
||||||
|
failedExpectations: [],
|
||||||
|
deprecationWarnings: [],
|
||||||
|
duration: null,
|
||||||
|
properties: null
|
||||||
|
};
|
||||||
|
this.markedPending = this.markedExcluding;
|
||||||
|
this.children.forEach(function(child) {
|
||||||
|
child.reset();
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
Suite.prototype.addChild = function(child) {
|
Suite.prototype.addChild = function(child) {
|
||||||
|
|||||||
Reference in New Issue
Block a user