Compare commits
11 Commits
v5.0.0-alp
...
v5.0.0-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
73f8e001ad | ||
|
|
390cc45af2 | ||
|
|
33118ac6e2 | ||
|
|
31ff9a300c | ||
|
|
5cc739d879 | ||
|
|
1e7f07259e | ||
|
|
c36a5cfd96 | ||
|
|
299fd1f770 | ||
|
|
656427d328 | ||
|
|
621522fdd4 | ||
|
|
6e3589bf52 |
@@ -4,16 +4,14 @@
|
|||||||
version: 2.1
|
version: 2.1
|
||||||
|
|
||||||
executors:
|
executors:
|
||||||
|
node20:
|
||||||
|
docker:
|
||||||
|
- image: cimg/node:20.0.0
|
||||||
|
working_directory: ~/workspace
|
||||||
node18:
|
node18:
|
||||||
docker:
|
docker:
|
||||||
- image: cimg/node:18.0.0
|
- image: cimg/node:18.0.0
|
||||||
working_directory: ~/workspace
|
working_directory: ~/workspace
|
||||||
node16:
|
|
||||||
docker:
|
|
||||||
# Oldest version with reliable support for error cause property,
|
|
||||||
# which jasmine-npm uses.
|
|
||||||
- image: cimg/node:16.14.0
|
|
||||||
working_directory: ~/workspace
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
@@ -62,7 +60,7 @@ jobs:
|
|||||||
command: npx grunt execSpecsInParallel
|
command: npx grunt execSpecsInParallel
|
||||||
|
|
||||||
test_browsers: &test_browsers
|
test_browsers: &test_browsers
|
||||||
executor: node16
|
executor: node18
|
||||||
steps:
|
steps:
|
||||||
- attach_workspace:
|
- attach_workspace:
|
||||||
at: .
|
at: .
|
||||||
@@ -96,35 +94,35 @@ workflows:
|
|||||||
|
|
||||||
push:
|
push:
|
||||||
jobs:
|
jobs:
|
||||||
|
- build:
|
||||||
|
executor: node20
|
||||||
|
name: build_node_20
|
||||||
- build:
|
- build:
|
||||||
executor: node18
|
executor: node18
|
||||||
name: build_node_18
|
name: build_node_18
|
||||||
- build:
|
- test_node:
|
||||||
executor: node16
|
executor: node20
|
||||||
name: build_node_16
|
name: test_node_20
|
||||||
|
requires:
|
||||||
|
- build_node_20
|
||||||
- test_node:
|
- test_node:
|
||||||
executor: node18
|
executor: node18
|
||||||
name: test_node_18
|
name: test_node_18
|
||||||
requires:
|
requires:
|
||||||
- build_node_18
|
- build_node_18
|
||||||
- test_node:
|
|
||||||
executor: node16
|
|
||||||
name: test_node_16
|
|
||||||
requires:
|
|
||||||
- build_node_16
|
|
||||||
- test_parallel:
|
|
||||||
executor: node16
|
|
||||||
name: test_parallel_node_16
|
|
||||||
requires:
|
|
||||||
- build_node_16
|
|
||||||
- test_parallel:
|
- test_parallel:
|
||||||
executor: node18
|
executor: node18
|
||||||
name: test_parallel_node_18
|
name: test_parallel_node_18
|
||||||
requires:
|
requires:
|
||||||
- build_node_18
|
- build_node_18
|
||||||
|
- test_parallel:
|
||||||
|
executor: node20
|
||||||
|
name: test_parallel_node_20
|
||||||
|
requires:
|
||||||
|
- build_node_20
|
||||||
- test_browsers:
|
- test_browsers:
|
||||||
requires:
|
requires:
|
||||||
- build_node_16
|
- build_node_18
|
||||||
filters:
|
filters:
|
||||||
branches:
|
branches:
|
||||||
ignore: /pull\/.*/ # Don't run on pull requests.
|
ignore: /pull\/.*/ # Don't run on pull requests.
|
||||||
|
|||||||
14
README.md
14
README.md
@@ -30,13 +30,13 @@ for information on writing specs, and [the FAQ](https://jasmine.github.io/pages/
|
|||||||
Jasmine tests itself across popular browsers (Safari, Chrome, Firefox, and
|
Jasmine tests itself across popular browsers (Safari, Chrome, Firefox, and
|
||||||
Microsoft Edge) as well as Node.
|
Microsoft Edge) as well as Node.
|
||||||
|
|
||||||
| Environment | Supported versions |
|
| Environment | Supported versions |
|
||||||
|-------------------|--------------------|
|
|-------------------|---------------------|
|
||||||
| Node | 16.14-16.19, 18 |
|
| Node | 18, 20 |
|
||||||
| Safari | 15-16 |
|
| Safari | 15-16 |
|
||||||
| Chrome | Evergreen |
|
| Chrome | Evergreen |
|
||||||
| Firefox | Evergreen, 102 |
|
| Firefox | Evergreen, 102 |
|
||||||
| Edge | Evergreen |
|
| Edge | Evergreen |
|
||||||
|
|
||||||
For evergreen browsers, each version of Jasmine is tested against the version of the browser that is available to us
|
For evergreen browsers, each version of Jasmine is tested against the version of the browser that is available to us
|
||||||
at the time of release. Other browsers, as well as older & newer versions of some supported browsers, are likely to work.
|
at the time of release. Other browsers, as well as older & newer versions of some supported browsers, are likely to work.
|
||||||
|
|||||||
@@ -89,7 +89,9 @@ var getJasmineRequireObj = (function(jasmineGlobal) {
|
|||||||
j$.CompleteOnFirstErrorSkipPolicy = jRequire.CompleteOnFirstErrorSkipPolicy(
|
j$.CompleteOnFirstErrorSkipPolicy = jRequire.CompleteOnFirstErrorSkipPolicy(
|
||||||
j$
|
j$
|
||||||
);
|
);
|
||||||
|
j$.reporterEvents = jRequire.reporterEvents(j$);
|
||||||
j$.ReportDispatcher = jRequire.ReportDispatcher(j$);
|
j$.ReportDispatcher = jRequire.ReportDispatcher(j$);
|
||||||
|
j$.ParallelReportDispatcher = jRequire.ParallelReportDispatcher(j$);
|
||||||
j$.RunableResources = jRequire.RunableResources(j$);
|
j$.RunableResources = jRequire.RunableResources(j$);
|
||||||
j$.Runner = jRequire.Runner(j$);
|
j$.Runner = jRequire.Runner(j$);
|
||||||
j$.Spec = jRequire.Spec(j$);
|
j$.Spec = jRequire.Spec(j$);
|
||||||
@@ -1309,6 +1311,12 @@ getJasmineRequireObj().Env = function(j$) {
|
|||||||
* @function
|
* @function
|
||||||
*/
|
*/
|
||||||
this.configure = function(configuration) {
|
this.configure = function(configuration) {
|
||||||
|
if (parallelLoadingState) {
|
||||||
|
throw new Error(
|
||||||
|
'Jasmine cannot be configured via Env in parallel mode'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const booleanProps = [
|
const booleanProps = [
|
||||||
'random',
|
'random',
|
||||||
'failSpecWithNoExpectations',
|
'failSpecWithNoExpectations',
|
||||||
@@ -1549,72 +1557,7 @@ getJasmineRequireObj().Env = function(j$) {
|
|||||||
* @see custom_reporter
|
* @see custom_reporter
|
||||||
*/
|
*/
|
||||||
reporter = new j$.ReportDispatcher(
|
reporter = new j$.ReportDispatcher(
|
||||||
[
|
j$.reporterEvents,
|
||||||
/**
|
|
||||||
* `jasmineStarted` is called after all of the specs have been loaded, but just before execution starts.
|
|
||||||
* @function
|
|
||||||
* @name Reporter#jasmineStarted
|
|
||||||
* @param {JasmineStartedInfo} suiteInfo Information about the full Jasmine suite that is being run
|
|
||||||
* @param {Function} [done] Used to specify to Jasmine that this callback is asynchronous and Jasmine should wait until it has been called before moving on.
|
|
||||||
* @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion.
|
|
||||||
* @see async
|
|
||||||
*/
|
|
||||||
'jasmineStarted',
|
|
||||||
/**
|
|
||||||
* When the entire suite has finished execution `jasmineDone` is called
|
|
||||||
* @function
|
|
||||||
* @name Reporter#jasmineDone
|
|
||||||
* @param {JasmineDoneInfo} suiteInfo Information about the full Jasmine suite that just finished running.
|
|
||||||
* @param {Function} [done] Used to specify to Jasmine that this callback is asynchronous and Jasmine should wait until it has been called before moving on.
|
|
||||||
* @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion.
|
|
||||||
* @see async
|
|
||||||
*/
|
|
||||||
'jasmineDone',
|
|
||||||
/**
|
|
||||||
* `suiteStarted` is invoked when a `describe` starts to run
|
|
||||||
* @function
|
|
||||||
* @name Reporter#suiteStarted
|
|
||||||
* @param {SuiteResult} result Information about the individual {@link describe} being run
|
|
||||||
* @param {Function} [done] Used to specify to Jasmine that this callback is asynchronous and Jasmine should wait until it has been called before moving on.
|
|
||||||
* @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion.
|
|
||||||
* @see async
|
|
||||||
*/
|
|
||||||
'suiteStarted',
|
|
||||||
/**
|
|
||||||
* `suiteDone` is invoked when all of the child specs and suites for a given suite have been run
|
|
||||||
*
|
|
||||||
* While jasmine doesn't require any specific functions, not defining a `suiteDone` will make it impossible for a reporter to know when a suite has failures in an `afterAll`.
|
|
||||||
* @function
|
|
||||||
* @name Reporter#suiteDone
|
|
||||||
* @param {SuiteResult} result
|
|
||||||
* @param {Function} [done] Used to specify to Jasmine that this callback is asynchronous and Jasmine should wait until it has been called before moving on.
|
|
||||||
* @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion.
|
|
||||||
* @see async
|
|
||||||
*/
|
|
||||||
'suiteDone',
|
|
||||||
/**
|
|
||||||
* `specStarted` is invoked when an `it` starts to run (including associated `beforeEach` functions)
|
|
||||||
* @function
|
|
||||||
* @name Reporter#specStarted
|
|
||||||
* @param {SpecResult} result Information about the individual {@link it} being run
|
|
||||||
* @param {Function} [done] Used to specify to Jasmine that this callback is asynchronous and Jasmine should wait until it has been called before moving on.
|
|
||||||
* @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion.
|
|
||||||
* @see async
|
|
||||||
*/
|
|
||||||
'specStarted',
|
|
||||||
/**
|
|
||||||
* `specDone` is invoked when an `it` and its associated `beforeEach` and `afterEach` functions have been run.
|
|
||||||
*
|
|
||||||
* While jasmine doesn't require any specific functions, not defining a `specDone` will make it impossible for a reporter to know when a spec has failed.
|
|
||||||
* @function
|
|
||||||
* @name Reporter#specDone
|
|
||||||
* @param {SpecResult} result
|
|
||||||
* @param {Function} [done] Used to specify to Jasmine that this callback is asynchronous and Jasmine should wait until it has been called before moving on.
|
|
||||||
* @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion.
|
|
||||||
* @see async
|
|
||||||
*/
|
|
||||||
'specDone'
|
|
||||||
],
|
|
||||||
function(options) {
|
function(options) {
|
||||||
options.SkipPolicy = j$.NeverSkipPolicy;
|
options.SkipPolicy = j$.NeverSkipPolicy;
|
||||||
return queueRunnerFactory(options);
|
return queueRunnerFactory(options);
|
||||||
@@ -1638,7 +1581,6 @@ getJasmineRequireObj().Env = function(j$) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
this.parallelReset = function() {
|
this.parallelReset = function() {
|
||||||
// TODO: ensure that autoCleanClosures was false
|
|
||||||
suiteBuilder.parallelReset();
|
suiteBuilder.parallelReset();
|
||||||
runner.parallelReset();
|
runner.parallelReset();
|
||||||
};
|
};
|
||||||
@@ -7167,6 +7109,100 @@ getJasmineRequireObj().NeverSkipPolicy = function(j$) {
|
|||||||
return NeverSkipPolicy;
|
return NeverSkipPolicy;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
getJasmineRequireObj().ParallelReportDispatcher = function(j$) {
|
||||||
|
/**
|
||||||
|
* @class ParallelReportDispatcher
|
||||||
|
* @implements Reporter
|
||||||
|
* @classdesc A report dispatcher packaged for convenient use from outside jasmine-core.
|
||||||
|
*
|
||||||
|
* This is intended to help packages like `jasmine` (the Jasmine runner for
|
||||||
|
* Node.js) do their own report dispatching in order to support parallel
|
||||||
|
* execution. If you aren't implementing a runner package that supports
|
||||||
|
* parallel execution, this class probably isn't what you're looking for.
|
||||||
|
*
|
||||||
|
* Warning: Do not use ParallelReportDispatcher in the same process that
|
||||||
|
* Jasmine specs run in. Doing so will break Jasmine's error handling.
|
||||||
|
* @param onError {function} Function called when an unhandled exception, unhandled promise rejection, or explicit reporter failure occurs
|
||||||
|
*/
|
||||||
|
function ParallelReportDispatcher(onError, deps = {}) {
|
||||||
|
const ReportDispatcher = deps.ReportDispatcher || j$.ReportDispatcher;
|
||||||
|
const QueueRunner = deps.QueueRunner || j$.QueueRunner;
|
||||||
|
const globalErrors = deps.globalErrors || new j$.GlobalErrors();
|
||||||
|
const dispatcher = ReportDispatcher(
|
||||||
|
j$.reporterEvents,
|
||||||
|
function(queueRunnerOptions) {
|
||||||
|
queueRunnerOptions = {
|
||||||
|
...queueRunnerOptions,
|
||||||
|
globalErrors,
|
||||||
|
timeout: { setTimeout, clearTimeout },
|
||||||
|
fail: function(error) {
|
||||||
|
// A callback-style async reporter called either done.fail()
|
||||||
|
// or done(anError).
|
||||||
|
if (!error) {
|
||||||
|
error = new Error('A reporter called done.fail()');
|
||||||
|
}
|
||||||
|
|
||||||
|
onError(error);
|
||||||
|
},
|
||||||
|
onException: function(error) {
|
||||||
|
// A reporter method threw an exception or returned a rejected
|
||||||
|
// promise, or there was an unhandled exception or unhandled promise
|
||||||
|
// rejection while an asynchronous reporter method was running.
|
||||||
|
onError(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
new QueueRunner(queueRunnerOptions).execute();
|
||||||
|
},
|
||||||
|
function(error) {
|
||||||
|
// A reporter called done() more than once.
|
||||||
|
onError(error);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const self = {
|
||||||
|
/**
|
||||||
|
* Adds a reporter to the list of reporters that events will be dispatched to.
|
||||||
|
* @function
|
||||||
|
* @name ParallelReportDispatcher#addReporter
|
||||||
|
* @param {Reporter} reporterToAdd The reporter to be added.
|
||||||
|
* @see custom_reporter
|
||||||
|
*/
|
||||||
|
addReporter: dispatcher.addReporter.bind(dispatcher),
|
||||||
|
/**
|
||||||
|
* Clears all registered reporters.
|
||||||
|
* @function
|
||||||
|
* @name ParallelReportDispatcher#clearReporters
|
||||||
|
*/
|
||||||
|
clearReporters: dispatcher.clearReporters.bind(dispatcher),
|
||||||
|
/**
|
||||||
|
* Installs a global error handler. After this method is called, any
|
||||||
|
* unhandled exceptions or unhandled promise rejections will be passed to
|
||||||
|
* the onError callback that was passed to the constructor.
|
||||||
|
* @function
|
||||||
|
* @name ParallelReportDispatcher#installGlobalErrors
|
||||||
|
*/
|
||||||
|
installGlobalErrors: globalErrors.install.bind(globalErrors),
|
||||||
|
/**
|
||||||
|
* Uninstalls the global error handler.
|
||||||
|
* @function
|
||||||
|
* @name ParallelReportDispatcher#uninstallGlobalErrors
|
||||||
|
*/
|
||||||
|
uninstallGlobalErrors: function() {
|
||||||
|
// late-bind uninstall because it doesn't exist until install is called
|
||||||
|
globalErrors.uninstall(globalErrors);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const eventName of j$.reporterEvents) {
|
||||||
|
self[eventName] = dispatcher[eventName].bind(dispatcher);
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ParallelReportDispatcher;
|
||||||
|
};
|
||||||
|
|
||||||
getJasmineRequireObj().makePrettyPrinter = function(j$) {
|
getJasmineRequireObj().makePrettyPrinter = function(j$) {
|
||||||
class SinglePrettyPrintRun {
|
class SinglePrettyPrintRun {
|
||||||
constructor(customObjectFormatters, pp) {
|
constructor(customObjectFormatters, pp) {
|
||||||
@@ -7528,15 +7564,6 @@ getJasmineRequireObj().makePrettyPrinter = function(j$) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
getJasmineRequireObj().QueueRunner = function(j$) {
|
getJasmineRequireObj().QueueRunner = function(j$) {
|
||||||
/*
|
|
||||||
QueueRunner isn't part of the public interface, but it is used by
|
|
||||||
jasmine-npm. -core and -npm version in lockstep at the major and minor
|
|
||||||
levels but version independently at the patch level. Any changes that
|
|
||||||
would break -npm should be done in a major or minor release, never a
|
|
||||||
patch release, and accompanied by a change to -npm that's released in
|
|
||||||
the same version.
|
|
||||||
*/
|
|
||||||
|
|
||||||
let nextid = 1;
|
let nextid = 1;
|
||||||
|
|
||||||
function StopExecutionError() {}
|
function StopExecutionError() {}
|
||||||
@@ -7793,17 +7820,21 @@ getJasmineRequireObj().QueueRunner = function(j$) {
|
|||||||
// on the stack at this point.
|
// on the stack at this point.
|
||||||
if (j$.isAsyncFunction_(fn)) {
|
if (j$.isAsyncFunction_(fn)) {
|
||||||
this.onException(
|
this.onException(
|
||||||
'An asynchronous before/it/after ' +
|
new Error(
|
||||||
'function was defined with the async keyword but also took a ' +
|
'An asynchronous before/it/after ' +
|
||||||
'done callback. Either remove the done callback (recommended) or ' +
|
'function was defined with the async keyword but also took a ' +
|
||||||
'remove the async keyword.'
|
'done callback. Either remove the done callback (recommended) or ' +
|
||||||
|
'remove the async keyword.'
|
||||||
|
)
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
this.onException(
|
this.onException(
|
||||||
'An asynchronous before/it/after ' +
|
new Error(
|
||||||
'function took a done callback but also returned a promise. ' +
|
'An asynchronous before/it/after ' +
|
||||||
'Either remove the done callback (recommended) or change the ' +
|
'function took a done callback but also returned a promise. ' +
|
||||||
'function to not return a promise.'
|
'Either remove the done callback (recommended) or change the ' +
|
||||||
|
'function to not return a promise.'
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7823,15 +7854,6 @@ getJasmineRequireObj().QueueRunner = function(j$) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
getJasmineRequireObj().ReportDispatcher = function(j$) {
|
getJasmineRequireObj().ReportDispatcher = function(j$) {
|
||||||
/*
|
|
||||||
ReportDispatcher isn't part of the public interface, but it is used by
|
|
||||||
jasmine-npm. -core and -npm version in lockstep at the major and minor
|
|
||||||
levels but version independently at the patch level. Any changes that
|
|
||||||
would break -npm should be done in a major or minor release, never a
|
|
||||||
patch release, and accompanied by a change to -npm that's released in
|
|
||||||
the same version.
|
|
||||||
*/
|
|
||||||
|
|
||||||
function ReportDispatcher(methods, queueRunnerFactory, onLateError) {
|
function ReportDispatcher(methods, queueRunnerFactory, onLateError) {
|
||||||
const dispatchedMethods = methods || [];
|
const dispatchedMethods = methods || [];
|
||||||
|
|
||||||
@@ -7912,6 +7934,77 @@ getJasmineRequireObj().ReportDispatcher = function(j$) {
|
|||||||
return ReportDispatcher;
|
return ReportDispatcher;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
getJasmineRequireObj().reporterEvents = function() {
|
||||||
|
const events = [
|
||||||
|
/**
|
||||||
|
* `jasmineStarted` is called after all of the specs have been loaded, but just before execution starts.
|
||||||
|
* @function
|
||||||
|
* @name Reporter#jasmineStarted
|
||||||
|
* @param {JasmineStartedInfo} suiteInfo Information about the full Jasmine suite that is being run
|
||||||
|
* @param {Function} [done] Used to specify to Jasmine that this callback is asynchronous and Jasmine should wait until it has been called before moving on.
|
||||||
|
* @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion.
|
||||||
|
* @see async
|
||||||
|
*/
|
||||||
|
'jasmineStarted',
|
||||||
|
/**
|
||||||
|
* When the entire suite has finished execution `jasmineDone` is called
|
||||||
|
* @function
|
||||||
|
* @name Reporter#jasmineDone
|
||||||
|
* @param {JasmineDoneInfo} suiteInfo Information about the full Jasmine suite that just finished running.
|
||||||
|
* @param {Function} [done] Used to specify to Jasmine that this callback is asynchronous and Jasmine should wait until it has been called before moving on.
|
||||||
|
* @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion.
|
||||||
|
* @see async
|
||||||
|
*/
|
||||||
|
'jasmineDone',
|
||||||
|
/**
|
||||||
|
* `suiteStarted` is invoked when a `describe` starts to run
|
||||||
|
* @function
|
||||||
|
* @name Reporter#suiteStarted
|
||||||
|
* @param {SuiteResult} result Information about the individual {@link describe} being run
|
||||||
|
* @param {Function} [done] Used to specify to Jasmine that this callback is asynchronous and Jasmine should wait until it has been called before moving on.
|
||||||
|
* @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion.
|
||||||
|
* @see async
|
||||||
|
*/
|
||||||
|
'suiteStarted',
|
||||||
|
/**
|
||||||
|
* `suiteDone` is invoked when all of the child specs and suites for a given suite have been run
|
||||||
|
*
|
||||||
|
* While jasmine doesn't require any specific functions, not defining a `suiteDone` will make it impossible for a reporter to know when a suite has failures in an `afterAll`.
|
||||||
|
* @function
|
||||||
|
* @name Reporter#suiteDone
|
||||||
|
* @param {SuiteResult} result
|
||||||
|
* @param {Function} [done] Used to specify to Jasmine that this callback is asynchronous and Jasmine should wait until it has been called before moving on.
|
||||||
|
* @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion.
|
||||||
|
* @see async
|
||||||
|
*/
|
||||||
|
'suiteDone',
|
||||||
|
/**
|
||||||
|
* `specStarted` is invoked when an `it` starts to run (including associated `beforeEach` functions)
|
||||||
|
* @function
|
||||||
|
* @name Reporter#specStarted
|
||||||
|
* @param {SpecResult} result Information about the individual {@link it} being run
|
||||||
|
* @param {Function} [done] Used to specify to Jasmine that this callback is asynchronous and Jasmine should wait until it has been called before moving on.
|
||||||
|
* @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion.
|
||||||
|
* @see async
|
||||||
|
*/
|
||||||
|
'specStarted',
|
||||||
|
/**
|
||||||
|
* `specDone` is invoked when an `it` and its associated `beforeEach` and `afterEach` functions have been run.
|
||||||
|
*
|
||||||
|
* While jasmine doesn't require any specific functions, not defining a `specDone` will make it impossible for a reporter to know when a spec has failed.
|
||||||
|
* @function
|
||||||
|
* @name Reporter#specDone
|
||||||
|
* @param {SpecResult} result
|
||||||
|
* @param {Function} [done] Used to specify to Jasmine that this callback is asynchronous and Jasmine should wait until it has been called before moving on.
|
||||||
|
* @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion.
|
||||||
|
* @see async
|
||||||
|
*/
|
||||||
|
'specDone'
|
||||||
|
];
|
||||||
|
Object.freeze(events);
|
||||||
|
return events;
|
||||||
|
};
|
||||||
|
|
||||||
getJasmineRequireObj().interface = function(jasmine, env) {
|
getJasmineRequireObj().interface = function(jasmine, env) {
|
||||||
const jasmineInterface = {
|
const jasmineInterface = {
|
||||||
/**
|
/**
|
||||||
@@ -10293,31 +10386,41 @@ getJasmineRequireObj().SuiteBuilder = function(j$) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
getJasmineRequireObj().Timer = function() {
|
getJasmineRequireObj().Timer = function() {
|
||||||
/*
|
|
||||||
Timer isn't part of the public interface, but it is used by
|
|
||||||
jasmine-npm. -core and -npm version in lockstep at the major and minor
|
|
||||||
levels but version independently at the patch level. Any changes that
|
|
||||||
would break -npm should be done in a major or minor release, never a
|
|
||||||
patch release, and accompanied by a change to -npm that's released in
|
|
||||||
the same version.
|
|
||||||
*/
|
|
||||||
|
|
||||||
const defaultNow = (function(Date) {
|
const defaultNow = (function(Date) {
|
||||||
return function() {
|
return function() {
|
||||||
return new Date().getTime();
|
return new Date().getTime();
|
||||||
};
|
};
|
||||||
})(Date);
|
})(Date);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class Timer
|
||||||
|
* @classdesc Tracks elapsed time
|
||||||
|
* @example
|
||||||
|
* const timer = new jasmine.Timer();
|
||||||
|
* timer.start();
|
||||||
|
* const elapsed = timer.elapsed()
|
||||||
|
*/
|
||||||
function Timer(options) {
|
function Timer(options) {
|
||||||
options = options || {};
|
options = options || {};
|
||||||
|
|
||||||
const now = options.now || defaultNow;
|
const now = options.now || defaultNow;
|
||||||
let startTime;
|
let startTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts the timer.
|
||||||
|
* @function
|
||||||
|
* @name Timer#start
|
||||||
|
*/
|
||||||
this.start = function() {
|
this.start = function() {
|
||||||
startTime = now();
|
startTime = now();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines the time since the timer was started.
|
||||||
|
* @function
|
||||||
|
* @name Timer#elapsed
|
||||||
|
* @returns {number} Elapsed time in milliseconds, or NaN if the timer has not been started
|
||||||
|
*/
|
||||||
this.elapsed = function() {
|
this.elapsed = function() {
|
||||||
return now() - startTime;
|
return now() - startTime;
|
||||||
};
|
};
|
||||||
@@ -10610,5 +10713,5 @@ getJasmineRequireObj().UserContext = function(j$) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
getJasmineRequireObj().version = function() {
|
getJasmineRequireObj().version = function() {
|
||||||
return '5.0.0-alpha.0';
|
return '5.0.0-beta.0';
|
||||||
};
|
};
|
||||||
|
|||||||
14
package.json
14
package.json
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "jasmine-core",
|
"name": "jasmine-core",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"version": "5.0.0-alpha.0",
|
"version": "5.0.0-beta.0",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/jasmine/jasmine.git"
|
"url": "https://github.com/jasmine/jasmine.git"
|
||||||
@@ -34,10 +34,10 @@
|
|||||||
"package.json"
|
"package.json"
|
||||||
],
|
],
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"eslint": "^7.32.0",
|
"eslint": "^8.36.0",
|
||||||
"eslint-plugin-compat": ">=4.0.0 <4.1.0",
|
"eslint-plugin-compat": "^4.0.0",
|
||||||
"glob": "^7.2.0",
|
"glob": "^9.3.1",
|
||||||
"grunt": ">=1.0.4 <1.6.0",
|
"grunt": "^1.0.4",
|
||||||
"grunt-cli": "^1.3.2",
|
"grunt-cli": "^1.3.2",
|
||||||
"grunt-contrib-compress": "^2.0.0",
|
"grunt-contrib-compress": "^2.0.0",
|
||||||
"grunt-contrib-concat": "^2.0.0",
|
"grunt-contrib-concat": "^2.0.0",
|
||||||
@@ -45,10 +45,10 @@
|
|||||||
"grunt-sass": "^3.0.2",
|
"grunt-sass": "^3.0.2",
|
||||||
"jasmine": "github:jasmine/jasmine-npm#5.0",
|
"jasmine": "github:jasmine/jasmine-npm#5.0",
|
||||||
"jasmine-browser-runner": "^1.0.0",
|
"jasmine-browser-runner": "^1.0.0",
|
||||||
"jsdom": "^19.0.0",
|
"jsdom": "^21.1.1",
|
||||||
"load-grunt-tasks": "^5.1.0",
|
"load-grunt-tasks": "^5.1.0",
|
||||||
"prettier": "1.17.1",
|
"prettier": "1.17.1",
|
||||||
"sass": "1.58.3",
|
"sass": "^1.58.3",
|
||||||
"shelljs": "^0.8.3",
|
"shelljs": "^0.8.3",
|
||||||
"temp": "^0.9.0"
|
"temp": "^0.9.0"
|
||||||
},
|
},
|
||||||
|
|||||||
39
release_notes/5.0.0-alpha.1.md
Normal file
39
release_notes/5.0.0-alpha.1.md
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
# Jasmine Core 5.0.0-alpha.1 Release Notes
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
This release provides improved support for parallel execution via the `jasmine`
|
||||||
|
package. Please see its release notes and the
|
||||||
|
[parallel documentation](https://jasmine.github.io/tutorials/running_specs_in_parallel)
|
||||||
|
for more information.
|
||||||
|
|
||||||
|
## New features and bug fixes
|
||||||
|
|
||||||
|
* Parallel: Cleaner interface for reporter dispatching
|
||||||
|
* When Env#config is called from spec and helper files in parallel mode, throw
|
||||||
|
an error rather than behaving unpredictably.
|
||||||
|
|
||||||
|
## Documentation improvements
|
||||||
|
|
||||||
|
* API reference docs for parallel support APIs that jasmine-npm uses
|
||||||
|
|
||||||
|
## Internal improvements
|
||||||
|
|
||||||
|
* Updated dev dependencies
|
||||||
|
|
||||||
|
## Supported environments
|
||||||
|
|
||||||
|
jasmine-core 5.0.0-alpha.1 has been tested in the following environments.
|
||||||
|
|
||||||
|
| Environment | Supported versions |
|
||||||
|
|-------------------|--------------------|
|
||||||
|
| Node | 16.14+, 18 |
|
||||||
|
| Safari | 15-16 |
|
||||||
|
| Chrome | 112 |
|
||||||
|
| Firefox | 102, 111 |
|
||||||
|
| Edge | 111 |
|
||||||
|
|
||||||
|
|
||||||
|
------
|
||||||
|
|
||||||
|
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
|
||||||
28
release_notes/5.0.0-beta.0.md
Normal file
28
release_notes/5.0.0-beta.0.md
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
# Jasmine Core 5.0.0-beta.0 Release Notes
|
||||||
|
|
||||||
|
This release supports the 5.0.0-beta-0 release of the `jasmine` package.
|
||||||
|
|
||||||
|
## Breaking changes
|
||||||
|
|
||||||
|
* Dropped support for Node 16
|
||||||
|
|
||||||
|
## New features
|
||||||
|
|
||||||
|
* Added support for Node 20
|
||||||
|
|
||||||
|
## Supported environments
|
||||||
|
|
||||||
|
jasmine-core 5.0.0-beta.0 has been tested in the following environments.
|
||||||
|
|
||||||
|
| Environment | Supported versions |
|
||||||
|
|-------------------|--------------------|
|
||||||
|
| Node | 18, 20 |
|
||||||
|
| Safari | 15-16 |
|
||||||
|
| Chrome | 112 |
|
||||||
|
| Firefox | 102, 112 |
|
||||||
|
| Edge | 112 |
|
||||||
|
|
||||||
|
|
||||||
|
------
|
||||||
|
|
||||||
|
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
|
||||||
@@ -758,16 +758,16 @@ describe('Env', function() {
|
|||||||
|
|
||||||
describe('In parallel mode', function() {
|
describe('In parallel mode', function() {
|
||||||
it('rejects if random is set to false', async function() {
|
it('rejects if random is set to false', async function() {
|
||||||
env.setParallelLoadingState('specs');
|
|
||||||
env.configure({ random: false });
|
env.configure({ random: false });
|
||||||
|
env.setParallelLoadingState('specs');
|
||||||
await expectAsync(env.execute()).toBeRejectedWithError(
|
await expectAsync(env.execute()).toBeRejectedWithError(
|
||||||
'Randomization cannot be disabled in parallel mode'
|
'Randomization cannot be disabled in parallel mode'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('rejects if seed is set', async function() {
|
it('rejects if seed is set', async function() {
|
||||||
env.setParallelLoadingState('specs');
|
|
||||||
env.configure({ seed: 1234 });
|
env.configure({ seed: 1234 });
|
||||||
|
env.setParallelLoadingState('specs');
|
||||||
await expectAsync(env.execute()).toBeRejectedWithError(
|
await expectAsync(env.execute()).toBeRejectedWithError(
|
||||||
'Random seed cannot be set in parallel mode'
|
'Random seed cannot be set in parallel mode'
|
||||||
);
|
);
|
||||||
@@ -817,4 +817,18 @@ describe('Env', function() {
|
|||||||
}).toThrowError('Reporters cannot be removed via Env in parallel mode');
|
}).toThrowError('Reporters cannot be removed via Env in parallel mode');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('#configure', function() {
|
||||||
|
it('throws when called in parallel mode', function() {
|
||||||
|
env.setParallelLoadingState('helpers');
|
||||||
|
expect(function() {
|
||||||
|
env.configure({});
|
||||||
|
}).toThrowError('Jasmine cannot be configured via Env in parallel mode');
|
||||||
|
|
||||||
|
env.setParallelLoadingState('specs');
|
||||||
|
expect(function() {
|
||||||
|
env.configure({});
|
||||||
|
}).toThrowError('Jasmine cannot be configured via Env in parallel mode');
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
176
spec/core/ParallelReportDispatcherSpec.js
Normal file
176
spec/core/ParallelReportDispatcherSpec.js
Normal file
@@ -0,0 +1,176 @@
|
|||||||
|
describe('ParallelReportDispatcher', function() {
|
||||||
|
it('dispatches the standard reporter events', async function() {
|
||||||
|
const subject = new jasmineUnderTest.ParallelReportDispatcher(() => {}, {
|
||||||
|
globalErrors: mockGlobalErrors()
|
||||||
|
});
|
||||||
|
const events = [
|
||||||
|
'jasmineStarted',
|
||||||
|
'jasmineDone',
|
||||||
|
'suiteStarted',
|
||||||
|
'suiteDone',
|
||||||
|
'specStarted',
|
||||||
|
'specDone'
|
||||||
|
];
|
||||||
|
const reporter = jasmine.createSpyObj('reporter', events);
|
||||||
|
subject.addReporter(reporter);
|
||||||
|
|
||||||
|
for (const eventName of events) {
|
||||||
|
const payload = { payloadFor: eventName };
|
||||||
|
await subject[eventName](payload);
|
||||||
|
expect(reporter[eventName]).toHaveBeenCalledWith(payload);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('installs and uninstalls the global error handler', function() {
|
||||||
|
const globalErrors = mockGlobalErrors();
|
||||||
|
const subject = new jasmineUnderTest.ParallelReportDispatcher(() => {}, {
|
||||||
|
globalErrors
|
||||||
|
});
|
||||||
|
|
||||||
|
subject.installGlobalErrors();
|
||||||
|
expect(globalErrors.install).toHaveBeenCalled();
|
||||||
|
|
||||||
|
subject.uninstallGlobalErrors();
|
||||||
|
expect(globalErrors.uninstall).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('handles global errors from async reporters', async function() {
|
||||||
|
const globalErrors = mockGlobalErrors();
|
||||||
|
const onError = jasmine.createSpy('onError');
|
||||||
|
const subject = new jasmineUnderTest.ParallelReportDispatcher(onError, {
|
||||||
|
globalErrors
|
||||||
|
});
|
||||||
|
const reporter = jasmine.createSpyObj('reporter', [
|
||||||
|
'jasmineStarted',
|
||||||
|
'jasmineDone'
|
||||||
|
]);
|
||||||
|
let resolveStarted;
|
||||||
|
reporter.jasmineStarted.and.callFake(function() {
|
||||||
|
return new Promise(function(res) {
|
||||||
|
resolveStarted = res;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
subject.addReporter(reporter);
|
||||||
|
|
||||||
|
const promise = subject.jasmineStarted({});
|
||||||
|
expect(globalErrors.pushListener).toHaveBeenCalled();
|
||||||
|
expect(globalErrors.popListener).not.toHaveBeenCalled();
|
||||||
|
const error = new Error('nope');
|
||||||
|
globalErrors.pushListener.calls.argsFor(0)[0](error);
|
||||||
|
expect(onError).toHaveBeenCalledWith(error);
|
||||||
|
|
||||||
|
resolveStarted();
|
||||||
|
await promise;
|
||||||
|
expect(globalErrors.popListener).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('handles done(error) from callback-style async reporters', function() {
|
||||||
|
const globalErrors = mockGlobalErrors();
|
||||||
|
const onError = jasmine.createSpy('onError');
|
||||||
|
const subject = new jasmineUnderTest.ParallelReportDispatcher(onError, {
|
||||||
|
globalErrors
|
||||||
|
});
|
||||||
|
const reporter = jasmine.createSpyObj('reporter', [
|
||||||
|
'jasmineStarted',
|
||||||
|
'jasmineDone'
|
||||||
|
]);
|
||||||
|
let callback;
|
||||||
|
reporter.jasmineStarted = function(event, cb) {
|
||||||
|
callback = cb;
|
||||||
|
};
|
||||||
|
subject.addReporter(reporter);
|
||||||
|
|
||||||
|
subject.jasmineStarted({});
|
||||||
|
|
||||||
|
expect(callback).toBeInstanceOf(Function);
|
||||||
|
const error = new Error('nope');
|
||||||
|
callback(error);
|
||||||
|
|
||||||
|
expect(onError).toHaveBeenCalledWith(error);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('handles done.fail() from callback-style async reporters', function() {
|
||||||
|
const globalErrors = mockGlobalErrors();
|
||||||
|
const onError = jasmine.createSpy('onError');
|
||||||
|
const subject = new jasmineUnderTest.ParallelReportDispatcher(onError, {
|
||||||
|
globalErrors
|
||||||
|
});
|
||||||
|
const reporter = jasmine.createSpyObj('reporter', [
|
||||||
|
'jasmineStarted',
|
||||||
|
'jasmineDone'
|
||||||
|
]);
|
||||||
|
let callback;
|
||||||
|
reporter.jasmineStarted = function(event, cb) {
|
||||||
|
callback = cb;
|
||||||
|
};
|
||||||
|
subject.addReporter(reporter);
|
||||||
|
|
||||||
|
subject.jasmineStarted({});
|
||||||
|
|
||||||
|
expect(callback).toBeInstanceOf(Function);
|
||||||
|
const error = new Error('nope');
|
||||||
|
callback.fail(error);
|
||||||
|
expect(onError).toHaveBeenCalledWith(error);
|
||||||
|
onError.calls.reset();
|
||||||
|
|
||||||
|
callback.fail();
|
||||||
|
expect(onError).toHaveBeenCalledWith(
|
||||||
|
new Error('A reporter called done.fail()')
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('handles errors due to mixed async style in reporters', async function() {
|
||||||
|
const globalErrors = mockGlobalErrors();
|
||||||
|
const onError = jasmine.createSpy('onError');
|
||||||
|
const subject = new jasmineUnderTest.ParallelReportDispatcher(onError, {
|
||||||
|
globalErrors
|
||||||
|
});
|
||||||
|
subject.addReporter({
|
||||||
|
async jasmineStarted(event, done) {
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
await subject.jasmineStarted({});
|
||||||
|
expect(onError).toHaveBeenCalledWith(
|
||||||
|
new Error(
|
||||||
|
'An asynchronous before/it/after function took a done callback but also returned a promise. Either remove the done callback (recommended) or change the function to not return a promise.'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('handles errors due to multiple done calls in reporters', async function() {
|
||||||
|
const globalErrors = mockGlobalErrors();
|
||||||
|
const onError = jasmine.createSpy('onError');
|
||||||
|
const subject = new jasmineUnderTest.ParallelReportDispatcher(onError, {
|
||||||
|
globalErrors
|
||||||
|
});
|
||||||
|
subject.addReporter({
|
||||||
|
jasmineStarted(event, done) {
|
||||||
|
done();
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
await subject.jasmineStarted({});
|
||||||
|
expect(onError).toHaveBeenCalledWith(
|
||||||
|
new Error(
|
||||||
|
"An asynchronous reporter callback called its 'done' callback more than once."
|
||||||
|
)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
function mockGlobalErrors() {
|
||||||
|
const globalErrors = jasmine.createSpyObj('globalErrors', [
|
||||||
|
'install',
|
||||||
|
'pushListener',
|
||||||
|
'popListener'
|
||||||
|
]);
|
||||||
|
|
||||||
|
globalErrors.install.and.callFake(function() {
|
||||||
|
globalErrors.uninstall = jasmine.createSpy('globalErrors.uninstall');
|
||||||
|
});
|
||||||
|
|
||||||
|
return globalErrors;
|
||||||
|
}
|
||||||
|
});
|
||||||
@@ -595,11 +595,13 @@ describe('QueueRunner', function() {
|
|||||||
queueRunner.execute();
|
queueRunner.execute();
|
||||||
|
|
||||||
expect(onException).toHaveBeenCalledWith(
|
expect(onException).toHaveBeenCalledWith(
|
||||||
'An asynchronous ' +
|
new Error(
|
||||||
'before/it/after function took a done callback but also returned a ' +
|
'An asynchronous ' +
|
||||||
'promise. ' +
|
'before/it/after function took a done callback but also returned a ' +
|
||||||
'Either remove the done callback (recommended) or change the function ' +
|
'promise. ' +
|
||||||
'to not return a promise.'
|
'Either remove the done callback (recommended) or change the function ' +
|
||||||
|
'to not return a promise.'
|
||||||
|
)
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -615,10 +617,12 @@ describe('QueueRunner', function() {
|
|||||||
queueRunner.execute();
|
queueRunner.execute();
|
||||||
|
|
||||||
expect(onException).toHaveBeenCalledWith(
|
expect(onException).toHaveBeenCalledWith(
|
||||||
'An asynchronous ' +
|
new Error(
|
||||||
'before/it/after function was defined with the async keyword but ' +
|
'An asynchronous ' +
|
||||||
'also took a done callback. Either remove the done callback ' +
|
'before/it/after function was defined with the async keyword but ' +
|
||||||
'(recommended) or remove the async keyword.'
|
'also took a done callback. Either remove the done callback ' +
|
||||||
|
'(recommended) or remove the async keyword.'
|
||||||
|
)
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -174,6 +174,12 @@ getJasmineRequireObj().Env = function(j$) {
|
|||||||
* @function
|
* @function
|
||||||
*/
|
*/
|
||||||
this.configure = function(configuration) {
|
this.configure = function(configuration) {
|
||||||
|
if (parallelLoadingState) {
|
||||||
|
throw new Error(
|
||||||
|
'Jasmine cannot be configured via Env in parallel mode'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const booleanProps = [
|
const booleanProps = [
|
||||||
'random',
|
'random',
|
||||||
'failSpecWithNoExpectations',
|
'failSpecWithNoExpectations',
|
||||||
@@ -414,72 +420,7 @@ getJasmineRequireObj().Env = function(j$) {
|
|||||||
* @see custom_reporter
|
* @see custom_reporter
|
||||||
*/
|
*/
|
||||||
reporter = new j$.ReportDispatcher(
|
reporter = new j$.ReportDispatcher(
|
||||||
[
|
j$.reporterEvents,
|
||||||
/**
|
|
||||||
* `jasmineStarted` is called after all of the specs have been loaded, but just before execution starts.
|
|
||||||
* @function
|
|
||||||
* @name Reporter#jasmineStarted
|
|
||||||
* @param {JasmineStartedInfo} suiteInfo Information about the full Jasmine suite that is being run
|
|
||||||
* @param {Function} [done] Used to specify to Jasmine that this callback is asynchronous and Jasmine should wait until it has been called before moving on.
|
|
||||||
* @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion.
|
|
||||||
* @see async
|
|
||||||
*/
|
|
||||||
'jasmineStarted',
|
|
||||||
/**
|
|
||||||
* When the entire suite has finished execution `jasmineDone` is called
|
|
||||||
* @function
|
|
||||||
* @name Reporter#jasmineDone
|
|
||||||
* @param {JasmineDoneInfo} suiteInfo Information about the full Jasmine suite that just finished running.
|
|
||||||
* @param {Function} [done] Used to specify to Jasmine that this callback is asynchronous and Jasmine should wait until it has been called before moving on.
|
|
||||||
* @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion.
|
|
||||||
* @see async
|
|
||||||
*/
|
|
||||||
'jasmineDone',
|
|
||||||
/**
|
|
||||||
* `suiteStarted` is invoked when a `describe` starts to run
|
|
||||||
* @function
|
|
||||||
* @name Reporter#suiteStarted
|
|
||||||
* @param {SuiteResult} result Information about the individual {@link describe} being run
|
|
||||||
* @param {Function} [done] Used to specify to Jasmine that this callback is asynchronous and Jasmine should wait until it has been called before moving on.
|
|
||||||
* @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion.
|
|
||||||
* @see async
|
|
||||||
*/
|
|
||||||
'suiteStarted',
|
|
||||||
/**
|
|
||||||
* `suiteDone` is invoked when all of the child specs and suites for a given suite have been run
|
|
||||||
*
|
|
||||||
* While jasmine doesn't require any specific functions, not defining a `suiteDone` will make it impossible for a reporter to know when a suite has failures in an `afterAll`.
|
|
||||||
* @function
|
|
||||||
* @name Reporter#suiteDone
|
|
||||||
* @param {SuiteResult} result
|
|
||||||
* @param {Function} [done] Used to specify to Jasmine that this callback is asynchronous and Jasmine should wait until it has been called before moving on.
|
|
||||||
* @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion.
|
|
||||||
* @see async
|
|
||||||
*/
|
|
||||||
'suiteDone',
|
|
||||||
/**
|
|
||||||
* `specStarted` is invoked when an `it` starts to run (including associated `beforeEach` functions)
|
|
||||||
* @function
|
|
||||||
* @name Reporter#specStarted
|
|
||||||
* @param {SpecResult} result Information about the individual {@link it} being run
|
|
||||||
* @param {Function} [done] Used to specify to Jasmine that this callback is asynchronous and Jasmine should wait until it has been called before moving on.
|
|
||||||
* @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion.
|
|
||||||
* @see async
|
|
||||||
*/
|
|
||||||
'specStarted',
|
|
||||||
/**
|
|
||||||
* `specDone` is invoked when an `it` and its associated `beforeEach` and `afterEach` functions have been run.
|
|
||||||
*
|
|
||||||
* While jasmine doesn't require any specific functions, not defining a `specDone` will make it impossible for a reporter to know when a spec has failed.
|
|
||||||
* @function
|
|
||||||
* @name Reporter#specDone
|
|
||||||
* @param {SpecResult} result
|
|
||||||
* @param {Function} [done] Used to specify to Jasmine that this callback is asynchronous and Jasmine should wait until it has been called before moving on.
|
|
||||||
* @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion.
|
|
||||||
* @see async
|
|
||||||
*/
|
|
||||||
'specDone'
|
|
||||||
],
|
|
||||||
function(options) {
|
function(options) {
|
||||||
options.SkipPolicy = j$.NeverSkipPolicy;
|
options.SkipPolicy = j$.NeverSkipPolicy;
|
||||||
return queueRunnerFactory(options);
|
return queueRunnerFactory(options);
|
||||||
@@ -503,7 +444,6 @@ getJasmineRequireObj().Env = function(j$) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
this.parallelReset = function() {
|
this.parallelReset = function() {
|
||||||
// TODO: ensure that autoCleanClosures was false
|
|
||||||
suiteBuilder.parallelReset();
|
suiteBuilder.parallelReset();
|
||||||
runner.parallelReset();
|
runner.parallelReset();
|
||||||
};
|
};
|
||||||
|
|||||||
93
src/core/ParallelReportDispatcher.js
Normal file
93
src/core/ParallelReportDispatcher.js
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
getJasmineRequireObj().ParallelReportDispatcher = function(j$) {
|
||||||
|
/**
|
||||||
|
* @class ParallelReportDispatcher
|
||||||
|
* @implements Reporter
|
||||||
|
* @classdesc A report dispatcher packaged for convenient use from outside jasmine-core.
|
||||||
|
*
|
||||||
|
* This is intended to help packages like `jasmine` (the Jasmine runner for
|
||||||
|
* Node.js) do their own report dispatching in order to support parallel
|
||||||
|
* execution. If you aren't implementing a runner package that supports
|
||||||
|
* parallel execution, this class probably isn't what you're looking for.
|
||||||
|
*
|
||||||
|
* Warning: Do not use ParallelReportDispatcher in the same process that
|
||||||
|
* Jasmine specs run in. Doing so will break Jasmine's error handling.
|
||||||
|
* @param onError {function} Function called when an unhandled exception, unhandled promise rejection, or explicit reporter failure occurs
|
||||||
|
*/
|
||||||
|
function ParallelReportDispatcher(onError, deps = {}) {
|
||||||
|
const ReportDispatcher = deps.ReportDispatcher || j$.ReportDispatcher;
|
||||||
|
const QueueRunner = deps.QueueRunner || j$.QueueRunner;
|
||||||
|
const globalErrors = deps.globalErrors || new j$.GlobalErrors();
|
||||||
|
const dispatcher = ReportDispatcher(
|
||||||
|
j$.reporterEvents,
|
||||||
|
function(queueRunnerOptions) {
|
||||||
|
queueRunnerOptions = {
|
||||||
|
...queueRunnerOptions,
|
||||||
|
globalErrors,
|
||||||
|
timeout: { setTimeout, clearTimeout },
|
||||||
|
fail: function(error) {
|
||||||
|
// A callback-style async reporter called either done.fail()
|
||||||
|
// or done(anError).
|
||||||
|
if (!error) {
|
||||||
|
error = new Error('A reporter called done.fail()');
|
||||||
|
}
|
||||||
|
|
||||||
|
onError(error);
|
||||||
|
},
|
||||||
|
onException: function(error) {
|
||||||
|
// A reporter method threw an exception or returned a rejected
|
||||||
|
// promise, or there was an unhandled exception or unhandled promise
|
||||||
|
// rejection while an asynchronous reporter method was running.
|
||||||
|
onError(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
new QueueRunner(queueRunnerOptions).execute();
|
||||||
|
},
|
||||||
|
function(error) {
|
||||||
|
// A reporter called done() more than once.
|
||||||
|
onError(error);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const self = {
|
||||||
|
/**
|
||||||
|
* Adds a reporter to the list of reporters that events will be dispatched to.
|
||||||
|
* @function
|
||||||
|
* @name ParallelReportDispatcher#addReporter
|
||||||
|
* @param {Reporter} reporterToAdd The reporter to be added.
|
||||||
|
* @see custom_reporter
|
||||||
|
*/
|
||||||
|
addReporter: dispatcher.addReporter.bind(dispatcher),
|
||||||
|
/**
|
||||||
|
* Clears all registered reporters.
|
||||||
|
* @function
|
||||||
|
* @name ParallelReportDispatcher#clearReporters
|
||||||
|
*/
|
||||||
|
clearReporters: dispatcher.clearReporters.bind(dispatcher),
|
||||||
|
/**
|
||||||
|
* Installs a global error handler. After this method is called, any
|
||||||
|
* unhandled exceptions or unhandled promise rejections will be passed to
|
||||||
|
* the onError callback that was passed to the constructor.
|
||||||
|
* @function
|
||||||
|
* @name ParallelReportDispatcher#installGlobalErrors
|
||||||
|
*/
|
||||||
|
installGlobalErrors: globalErrors.install.bind(globalErrors),
|
||||||
|
/**
|
||||||
|
* Uninstalls the global error handler.
|
||||||
|
* @function
|
||||||
|
* @name ParallelReportDispatcher#uninstallGlobalErrors
|
||||||
|
*/
|
||||||
|
uninstallGlobalErrors: function() {
|
||||||
|
// late-bind uninstall because it doesn't exist until install is called
|
||||||
|
globalErrors.uninstall(globalErrors);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const eventName of j$.reporterEvents) {
|
||||||
|
self[eventName] = dispatcher[eventName].bind(dispatcher);
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ParallelReportDispatcher;
|
||||||
|
};
|
||||||
@@ -1,13 +1,4 @@
|
|||||||
getJasmineRequireObj().QueueRunner = function(j$) {
|
getJasmineRequireObj().QueueRunner = function(j$) {
|
||||||
/*
|
|
||||||
QueueRunner isn't part of the public interface, but it is used by
|
|
||||||
jasmine-npm. -core and -npm version in lockstep at the major and minor
|
|
||||||
levels but version independently at the patch level. Any changes that
|
|
||||||
would break -npm should be done in a major or minor release, never a
|
|
||||||
patch release, and accompanied by a change to -npm that's released in
|
|
||||||
the same version.
|
|
||||||
*/
|
|
||||||
|
|
||||||
let nextid = 1;
|
let nextid = 1;
|
||||||
|
|
||||||
function StopExecutionError() {}
|
function StopExecutionError() {}
|
||||||
@@ -264,17 +255,21 @@ getJasmineRequireObj().QueueRunner = function(j$) {
|
|||||||
// on the stack at this point.
|
// on the stack at this point.
|
||||||
if (j$.isAsyncFunction_(fn)) {
|
if (j$.isAsyncFunction_(fn)) {
|
||||||
this.onException(
|
this.onException(
|
||||||
'An asynchronous before/it/after ' +
|
new Error(
|
||||||
'function was defined with the async keyword but also took a ' +
|
'An asynchronous before/it/after ' +
|
||||||
'done callback. Either remove the done callback (recommended) or ' +
|
'function was defined with the async keyword but also took a ' +
|
||||||
'remove the async keyword.'
|
'done callback. Either remove the done callback (recommended) or ' +
|
||||||
|
'remove the async keyword.'
|
||||||
|
)
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
this.onException(
|
this.onException(
|
||||||
'An asynchronous before/it/after ' +
|
new Error(
|
||||||
'function took a done callback but also returned a promise. ' +
|
'An asynchronous before/it/after ' +
|
||||||
'Either remove the done callback (recommended) or change the ' +
|
'function took a done callback but also returned a promise. ' +
|
||||||
'function to not return a promise.'
|
'Either remove the done callback (recommended) or change the ' +
|
||||||
|
'function to not return a promise.'
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,4 @@
|
|||||||
getJasmineRequireObj().ReportDispatcher = function(j$) {
|
getJasmineRequireObj().ReportDispatcher = function(j$) {
|
||||||
/*
|
|
||||||
ReportDispatcher isn't part of the public interface, but it is used by
|
|
||||||
jasmine-npm. -core and -npm version in lockstep at the major and minor
|
|
||||||
levels but version independently at the patch level. Any changes that
|
|
||||||
would break -npm should be done in a major or minor release, never a
|
|
||||||
patch release, and accompanied by a change to -npm that's released in
|
|
||||||
the same version.
|
|
||||||
*/
|
|
||||||
|
|
||||||
function ReportDispatcher(methods, queueRunnerFactory, onLateError) {
|
function ReportDispatcher(methods, queueRunnerFactory, onLateError) {
|
||||||
const dispatchedMethods = methods || [];
|
const dispatchedMethods = methods || [];
|
||||||
|
|
||||||
|
|||||||
@@ -1,29 +1,39 @@
|
|||||||
getJasmineRequireObj().Timer = function() {
|
getJasmineRequireObj().Timer = function() {
|
||||||
/*
|
|
||||||
Timer isn't part of the public interface, but it is used by
|
|
||||||
jasmine-npm. -core and -npm version in lockstep at the major and minor
|
|
||||||
levels but version independently at the patch level. Any changes that
|
|
||||||
would break -npm should be done in a major or minor release, never a
|
|
||||||
patch release, and accompanied by a change to -npm that's released in
|
|
||||||
the same version.
|
|
||||||
*/
|
|
||||||
|
|
||||||
const defaultNow = (function(Date) {
|
const defaultNow = (function(Date) {
|
||||||
return function() {
|
return function() {
|
||||||
return new Date().getTime();
|
return new Date().getTime();
|
||||||
};
|
};
|
||||||
})(Date);
|
})(Date);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class Timer
|
||||||
|
* @classdesc Tracks elapsed time
|
||||||
|
* @example
|
||||||
|
* const timer = new jasmine.Timer();
|
||||||
|
* timer.start();
|
||||||
|
* const elapsed = timer.elapsed()
|
||||||
|
*/
|
||||||
function Timer(options) {
|
function Timer(options) {
|
||||||
options = options || {};
|
options = options || {};
|
||||||
|
|
||||||
const now = options.now || defaultNow;
|
const now = options.now || defaultNow;
|
||||||
let startTime;
|
let startTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts the timer.
|
||||||
|
* @function
|
||||||
|
* @name Timer#start
|
||||||
|
*/
|
||||||
this.start = function() {
|
this.start = function() {
|
||||||
startTime = now();
|
startTime = now();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines the time since the timer was started.
|
||||||
|
* @function
|
||||||
|
* @name Timer#elapsed
|
||||||
|
* @returns {number} Elapsed time in milliseconds, or NaN if the timer has not been started
|
||||||
|
*/
|
||||||
this.elapsed = function() {
|
this.elapsed = function() {
|
||||||
return now() - startTime;
|
return now() - startTime;
|
||||||
};
|
};
|
||||||
|
|||||||
70
src/core/reporterEvents.js
Normal file
70
src/core/reporterEvents.js
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
getJasmineRequireObj().reporterEvents = function() {
|
||||||
|
const events = [
|
||||||
|
/**
|
||||||
|
* `jasmineStarted` is called after all of the specs have been loaded, but just before execution starts.
|
||||||
|
* @function
|
||||||
|
* @name Reporter#jasmineStarted
|
||||||
|
* @param {JasmineStartedInfo} suiteInfo Information about the full Jasmine suite that is being run
|
||||||
|
* @param {Function} [done] Used to specify to Jasmine that this callback is asynchronous and Jasmine should wait until it has been called before moving on.
|
||||||
|
* @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion.
|
||||||
|
* @see async
|
||||||
|
*/
|
||||||
|
'jasmineStarted',
|
||||||
|
/**
|
||||||
|
* When the entire suite has finished execution `jasmineDone` is called
|
||||||
|
* @function
|
||||||
|
* @name Reporter#jasmineDone
|
||||||
|
* @param {JasmineDoneInfo} suiteInfo Information about the full Jasmine suite that just finished running.
|
||||||
|
* @param {Function} [done] Used to specify to Jasmine that this callback is asynchronous and Jasmine should wait until it has been called before moving on.
|
||||||
|
* @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion.
|
||||||
|
* @see async
|
||||||
|
*/
|
||||||
|
'jasmineDone',
|
||||||
|
/**
|
||||||
|
* `suiteStarted` is invoked when a `describe` starts to run
|
||||||
|
* @function
|
||||||
|
* @name Reporter#suiteStarted
|
||||||
|
* @param {SuiteResult} result Information about the individual {@link describe} being run
|
||||||
|
* @param {Function} [done] Used to specify to Jasmine that this callback is asynchronous and Jasmine should wait until it has been called before moving on.
|
||||||
|
* @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion.
|
||||||
|
* @see async
|
||||||
|
*/
|
||||||
|
'suiteStarted',
|
||||||
|
/**
|
||||||
|
* `suiteDone` is invoked when all of the child specs and suites for a given suite have been run
|
||||||
|
*
|
||||||
|
* While jasmine doesn't require any specific functions, not defining a `suiteDone` will make it impossible for a reporter to know when a suite has failures in an `afterAll`.
|
||||||
|
* @function
|
||||||
|
* @name Reporter#suiteDone
|
||||||
|
* @param {SuiteResult} result
|
||||||
|
* @param {Function} [done] Used to specify to Jasmine that this callback is asynchronous and Jasmine should wait until it has been called before moving on.
|
||||||
|
* @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion.
|
||||||
|
* @see async
|
||||||
|
*/
|
||||||
|
'suiteDone',
|
||||||
|
/**
|
||||||
|
* `specStarted` is invoked when an `it` starts to run (including associated `beforeEach` functions)
|
||||||
|
* @function
|
||||||
|
* @name Reporter#specStarted
|
||||||
|
* @param {SpecResult} result Information about the individual {@link it} being run
|
||||||
|
* @param {Function} [done] Used to specify to Jasmine that this callback is asynchronous and Jasmine should wait until it has been called before moving on.
|
||||||
|
* @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion.
|
||||||
|
* @see async
|
||||||
|
*/
|
||||||
|
'specStarted',
|
||||||
|
/**
|
||||||
|
* `specDone` is invoked when an `it` and its associated `beforeEach` and `afterEach` functions have been run.
|
||||||
|
*
|
||||||
|
* While jasmine doesn't require any specific functions, not defining a `specDone` will make it impossible for a reporter to know when a spec has failed.
|
||||||
|
* @function
|
||||||
|
* @name Reporter#specDone
|
||||||
|
* @param {SpecResult} result
|
||||||
|
* @param {Function} [done] Used to specify to Jasmine that this callback is asynchronous and Jasmine should wait until it has been called before moving on.
|
||||||
|
* @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion.
|
||||||
|
* @see async
|
||||||
|
*/
|
||||||
|
'specDone'
|
||||||
|
];
|
||||||
|
Object.freeze(events);
|
||||||
|
return events;
|
||||||
|
};
|
||||||
@@ -67,7 +67,9 @@ var getJasmineRequireObj = (function(jasmineGlobal) {
|
|||||||
j$.CompleteOnFirstErrorSkipPolicy = jRequire.CompleteOnFirstErrorSkipPolicy(
|
j$.CompleteOnFirstErrorSkipPolicy = jRequire.CompleteOnFirstErrorSkipPolicy(
|
||||||
j$
|
j$
|
||||||
);
|
);
|
||||||
|
j$.reporterEvents = jRequire.reporterEvents(j$);
|
||||||
j$.ReportDispatcher = jRequire.ReportDispatcher(j$);
|
j$.ReportDispatcher = jRequire.ReportDispatcher(j$);
|
||||||
|
j$.ParallelReportDispatcher = jRequire.ParallelReportDispatcher(j$);
|
||||||
j$.RunableResources = jRequire.RunableResources(j$);
|
j$.RunableResources = jRequire.RunableResources(j$);
|
||||||
j$.Runner = jRequire.Runner(j$);
|
j$.Runner = jRequire.Runner(j$);
|
||||||
j$.Spec = jRequire.Spec(j$);
|
j$.Spec = jRequire.Spec(j$);
|
||||||
|
|||||||
Reference in New Issue
Block a user