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:
Nico Jansen
2021-10-01 16:12:57 +02:00
parent fdad8849df
commit 1fc911e0fa
6 changed files with 438 additions and 44 deletions

View File

@@ -138,7 +138,16 @@ getJasmineRequireObj().Env = function(j$) {
* @type function
* @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() {
@@ -191,7 +200,8 @@ getJasmineRequireObj().Env = function(j$) {
var booleanProps = [
'random',
'failSpecWithNoExpectations',
'hideDisabled'
'hideDisabled',
'autoCleanClosures'
];
booleanProps.forEach(function(prop) {
@@ -497,10 +507,11 @@ getJasmineRequireObj().Env = function(j$) {
delete runnableResources[id];
};
var beforeAndAfterFns = function(suite) {
var beforeAndAfterFns = function(targetSuite) {
return function() {
var befores = [],
afters = [];
afters = [],
suite = targetSuite;
while (suite) {
befores = befores.concat(suite.beforeFns);
@@ -701,9 +712,9 @@ getJasmineRequireObj().Env = function(j$) {
description: 'Jasmine__TopLevel__Suite',
expectationFactory: expectationFactory,
asyncExpectationFactory: suiteAsyncExpectationFactory,
expectationResultFactory: expectationResultFactory
expectationResultFactory: expectationResultFactory,
autoCleanClosures: config.autoCleanClosures
});
defaultResourcesForRunnable(topSuite.id);
currentDeclarationSuite = topSuite;
/**
@@ -821,6 +832,11 @@ getJasmineRequireObj().Env = function(j$) {
* @return {Promise<undefined>}
*/
this.execute = function(runnablesToRun, onComplete) {
if (this._executedBefore) {
topSuite.reset();
}
this._executedBefore = true;
defaultResourcesForRunnable(topSuite.id);
installGlobalErrors();
if (!runnablesToRun) {
@@ -1107,7 +1123,8 @@ getJasmineRequireObj().Env = function(j$) {
expectationFactory: expectationFactory,
asyncExpectationFactory: suiteAsyncExpectationFactory,
expectationResultFactory: expectationResultFactory,
throwOnExpectationFailure: config.oneFailurePerSpec
throwOnExpectationFailure: config.oneFailurePerSpec,
autoCleanClosures: config.autoCleanClosures
});
return suite;
@@ -1120,8 +1137,8 @@ getJasmineRequireObj().Env = function(j$) {
if (specDefinitions.length > 0) {
throw new Error('describe does not expect any arguments');
}
if (currentDeclarationSuite.markedPending) {
suite.pend();
if (currentDeclarationSuite.markedExcluding) {
suite.exclude();
}
addSpecsToSuite(suite, specDefinitions);
return suite;
@@ -1131,7 +1148,7 @@ getJasmineRequireObj().Env = function(j$) {
ensureIsNotNested('xdescribe');
ensureIsFunction(specDefinitions, 'xdescribe');
var suite = suiteFactory(description);
suite.pend();
suite.exclude();
addSpecsToSuite(suite, specDefinitions);
return suite;
};
@@ -1216,6 +1233,7 @@ getJasmineRequireObj().Env = function(j$) {
timeout: timeout || 0
},
throwOnExpectationFailure: config.oneFailurePerSpec,
autoCleanClosures: config.autoCleanClosures,
timer: new j$.Timer()
});
return spec;
@@ -1251,8 +1269,8 @@ getJasmineRequireObj().Env = function(j$) {
}
var spec = specFactory(description, fn, currentDeclarationSuite, timeout);
if (currentDeclarationSuite.markedPending) {
spec.pend();
if (currentDeclarationSuite.markedExcluding) {
spec.exclude();
}
currentDeclarationSuite.addChild(spec);
return spec;
@@ -1266,7 +1284,7 @@ getJasmineRequireObj().Env = function(j$) {
ensureIsFunctionOrAsync(fn, 'xit');
}
var spec = this.it.apply(this, arguments);
spec.pend('Temporarily disabled with xit');
spec.exclude('Temporarily disabled with xit');
return spec;
};