jasmine-core 4.6.0 → 5.0.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -32,10 +32,10 @@ Microsoft Edge) as well as Node.
32
32
 
33
33
  | Environment | Supported versions |
34
34
  |-------------------|--------------------|
35
- | Node | 12.17+, 14, 16, 18 |
36
- | Safari | 14-16 |
35
+ | Node | 16.14-16.19, 18 |
36
+ | Safari | 15-16 |
37
37
  | Chrome | Evergreen |
38
- | Firefox | Evergreen, 91, 102 |
38
+ | Firefox | Evergreen, 102 |
39
39
  | Edge | Evergreen |
40
40
 
41
41
  For evergreen browsers, each version of Jasmine is tested against the version of the browser that is available to us
@@ -89,7 +89,9 @@ var getJasmineRequireObj = (function(jasmineGlobal) {
89
89
  j$.CompleteOnFirstErrorSkipPolicy = jRequire.CompleteOnFirstErrorSkipPolicy(
90
90
  j$
91
91
  );
92
+ j$.reporterEvents = jRequire.reporterEvents(j$);
92
93
  j$.ReportDispatcher = jRequire.ReportDispatcher(j$);
94
+ j$.ParallelReportDispatcher = jRequire.ParallelReportDispatcher(j$);
93
95
  j$.RunableResources = jRequire.RunableResources(j$);
94
96
  j$.Runner = jRequire.Runner(j$);
95
97
  j$.Spec = jRequire.Spec(j$);
@@ -1181,6 +1183,7 @@ getJasmineRequireObj().Env = function(j$) {
1181
1183
  let reporter;
1182
1184
  let topSuite;
1183
1185
  let runner;
1186
+ let parallelLoadingState = null; // 'specs', 'helpers', or null for non-parallel
1184
1187
 
1185
1188
  /**
1186
1189
  * This represents the available options to configure Jasmine.
@@ -1209,6 +1212,10 @@ getJasmineRequireObj().Env = function(j$) {
1209
1212
  seed: null,
1210
1213
  /**
1211
1214
  * Whether to stop execution of the suite after the first spec failure
1215
+ *
1216
+ * <p>In parallel mode, `stopOnSpecFailure` works on a "best effort"
1217
+ * basis. Jasmine will stop execution as soon as practical after a failure
1218
+ * but it might not be immediate.</p>
1212
1219
  * @name Configuration#stopOnSpecFailure
1213
1220
  * @since 3.9.0
1214
1221
  * @type Boolean
@@ -1284,20 +1291,14 @@ getJasmineRequireObj().Env = function(j$) {
1284
1291
 
1285
1292
  if (!options.suppressLoadErrors) {
1286
1293
  installGlobalErrors();
1287
- globalErrors.pushListener(function loadtimeErrorHandler(
1288
- message,
1289
- filename,
1290
- lineno,
1291
- colNo,
1292
- err
1293
- ) {
1294
+ globalErrors.pushListener(function loadtimeErrorHandler(error, event) {
1294
1295
  topSuite.result.failedExpectations.push({
1295
1296
  passed: false,
1296
1297
  globalErrorType: 'load',
1297
- message: message,
1298
- stack: err && err.stack,
1299
- filename: filename,
1300
- lineno: lineno
1298
+ message: error ? error.message : event.message,
1299
+ stack: error && error.stack,
1300
+ filename: event && event.filename,
1301
+ lineno: event && event.lineno
1301
1302
  });
1302
1303
  });
1303
1304
  }
@@ -1310,6 +1311,12 @@ getJasmineRequireObj().Env = function(j$) {
1310
1311
  * @function
1311
1312
  */
1312
1313
  this.configure = function(configuration) {
1314
+ if (parallelLoadingState) {
1315
+ throw new Error(
1316
+ 'Jasmine cannot be configured via Env in parallel mode'
1317
+ );
1318
+ }
1319
+
1313
1320
  const booleanProps = [
1314
1321
  'random',
1315
1322
  'failSpecWithNoExpectations',
@@ -1515,7 +1522,6 @@ getJasmineRequireObj().Env = function(j$) {
1515
1522
  function(e) {
1516
1523
  (runner.currentRunable() || topSuite).handleException(e);
1517
1524
  };
1518
- options.deprecated = self.deprecated;
1519
1525
 
1520
1526
  new j$.QueueRunner(options).execute();
1521
1527
  }
@@ -1541,6 +1547,7 @@ getJasmineRequireObj().Env = function(j$) {
1541
1547
  * @since 2.0.0
1542
1548
  */
1543
1549
  this.topSuite = function() {
1550
+ ensureNonParallel('topSuite');
1544
1551
  return topSuite.metadata;
1545
1552
  };
1546
1553
 
@@ -1550,72 +1557,7 @@ getJasmineRequireObj().Env = function(j$) {
1550
1557
  * @see custom_reporter
1551
1558
  */
1552
1559
  reporter = new j$.ReportDispatcher(
1553
- [
1554
- /**
1555
- * `jasmineStarted` is called after all of the specs have been loaded, but just before execution starts.
1556
- * @function
1557
- * @name Reporter#jasmineStarted
1558
- * @param {JasmineStartedInfo} suiteInfo Information about the full Jasmine suite that is being run
1559
- * @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.
1560
- * @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion.
1561
- * @see async
1562
- */
1563
- 'jasmineStarted',
1564
- /**
1565
- * When the entire suite has finished execution `jasmineDone` is called
1566
- * @function
1567
- * @name Reporter#jasmineDone
1568
- * @param {JasmineDoneInfo} suiteInfo Information about the full Jasmine suite that just finished running.
1569
- * @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.
1570
- * @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion.
1571
- * @see async
1572
- */
1573
- 'jasmineDone',
1574
- /**
1575
- * `suiteStarted` is invoked when a `describe` starts to run
1576
- * @function
1577
- * @name Reporter#suiteStarted
1578
- * @param {SuiteResult} result Information about the individual {@link describe} being run
1579
- * @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.
1580
- * @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion.
1581
- * @see async
1582
- */
1583
- 'suiteStarted',
1584
- /**
1585
- * `suiteDone` is invoked when all of the child specs and suites for a given suite have been run
1586
- *
1587
- * 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`.
1588
- * @function
1589
- * @name Reporter#suiteDone
1590
- * @param {SuiteResult} result
1591
- * @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.
1592
- * @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion.
1593
- * @see async
1594
- */
1595
- 'suiteDone',
1596
- /**
1597
- * `specStarted` is invoked when an `it` starts to run (including associated `beforeEach` functions)
1598
- * @function
1599
- * @name Reporter#specStarted
1600
- * @param {SpecResult} result Information about the individual {@link it} being run
1601
- * @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.
1602
- * @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion.
1603
- * @see async
1604
- */
1605
- 'specStarted',
1606
- /**
1607
- * `specDone` is invoked when an `it` and its associated `beforeEach` and `afterEach` functions have been run.
1608
- *
1609
- * 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.
1610
- * @function
1611
- * @name Reporter#specDone
1612
- * @param {SpecResult} result
1613
- * @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.
1614
- * @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion.
1615
- * @see async
1616
- */
1617
- 'specDone'
1618
- ],
1560
+ j$.reporterEvents,
1619
1561
  function(options) {
1620
1562
  options.SkipPolicy = j$.NeverSkipPolicy;
1621
1563
  return queueRunnerFactory(options);
@@ -1634,21 +1576,24 @@ getJasmineRequireObj().Env = function(j$) {
1634
1576
  reportSpecDone
1635
1577
  });
1636
1578
 
1579
+ this.setParallelLoadingState = function(state) {
1580
+ parallelLoadingState = state;
1581
+ };
1582
+
1583
+ this.parallelReset = function() {
1584
+ suiteBuilder.parallelReset();
1585
+ runner.parallelReset();
1586
+ };
1587
+
1637
1588
  /**
1638
1589
  * Executes the specs.
1639
1590
  *
1640
- * If called with no parameters or with a falsy value as the first parameter,
1591
+ * If called with no parameter or with a falsy parameter,
1641
1592
  * all specs will be executed except those that are excluded by a
1642
1593
  * [spec filter]{@link Configuration#specFilter} or other mechanism. If the
1643
- * first parameter is a list of spec/suite IDs, only those specs/suites will
1594
+ * parameter is a list of spec/suite IDs, only those specs/suites will
1644
1595
  * be run.
1645
1596
  *
1646
- * Both parameters are optional, but a completion callback is only valid as
1647
- * the second parameter. To specify a completion callback but not a list of
1648
- * specs/suites to run, pass null or undefined as the first parameter. The
1649
- * completion callback is supported for backward compatibility. In most
1650
- * cases it will be more convenient to use the returned promise instead.
1651
- *
1652
1597
  * execute should not be called more than once unless the env has been
1653
1598
  * configured with `{autoCleanClosures: false}`.
1654
1599
  *
@@ -1656,25 +1601,26 @@ getJasmineRequireObj().Env = function(j$) {
1656
1601
  * {@link JasmineDoneInfo|overall result} that's passed to a reporter's
1657
1602
  * `jasmineDone` method, even if the suite did not pass. To determine
1658
1603
  * whether the suite passed, check the value that the promise resolves to
1659
- * or use a {@link Reporter}.
1604
+ * or use a {@link Reporter}. The promise will be rejected in the case of
1605
+ * certain serious errors that prevent execution from starting.
1660
1606
  *
1661
1607
  * @name Env#execute
1662
1608
  * @since 2.0.0
1663
1609
  * @function
1610
+ * @async
1664
1611
  * @param {(string[])=} runablesToRun IDs of suites and/or specs to run
1665
- * @param {Function=} onComplete Function that will be called after all specs have run
1666
1612
  * @return {Promise<JasmineDoneInfo>}
1667
1613
  */
1668
- this.execute = function(runablesToRun, onComplete) {
1614
+ this.execute = async function(runablesToRun) {
1669
1615
  installGlobalErrors();
1670
1616
 
1671
- return runner.execute(runablesToRun).then(function(jasmineDoneInfo) {
1672
- if (onComplete) {
1673
- onComplete();
1674
- }
1617
+ if (parallelLoadingState) {
1618
+ validateConfigForParallel();
1619
+ }
1675
1620
 
1676
- return jasmineDoneInfo;
1677
- });
1621
+ const result = await runner.execute(runablesToRun);
1622
+ this.cleanup_();
1623
+ return result;
1678
1624
  };
1679
1625
 
1680
1626
  /**
@@ -1686,6 +1632,10 @@ getJasmineRequireObj().Env = function(j$) {
1686
1632
  * @see custom_reporter
1687
1633
  */
1688
1634
  this.addReporter = function(reporterToAdd) {
1635
+ if (parallelLoadingState) {
1636
+ throw new Error('Reporters cannot be added via Env in parallel mode');
1637
+ }
1638
+
1689
1639
  reporter.addReporter(reporterToAdd);
1690
1640
  };
1691
1641
 
@@ -1708,6 +1658,10 @@ getJasmineRequireObj().Env = function(j$) {
1708
1658
  * @function
1709
1659
  */
1710
1660
  this.clearReporters = function() {
1661
+ if (parallelLoadingState) {
1662
+ throw new Error('Reporters cannot be removed via Env in parallel mode');
1663
+ }
1664
+
1711
1665
  reporter.clearReporters();
1712
1666
  };
1713
1667
 
@@ -1807,6 +1761,38 @@ getJasmineRequireObj().Env = function(j$) {
1807
1761
  }
1808
1762
  }
1809
1763
 
1764
+ function ensureNonParallel(method) {
1765
+ if (parallelLoadingState) {
1766
+ throw new Error(`'${method}' is not available in parallel mode`);
1767
+ }
1768
+ }
1769
+
1770
+ function ensureNonParallelOrInDescribe(msg) {
1771
+ if (parallelLoadingState && !suiteBuilder.inDescribe()) {
1772
+ throw new Error(msg);
1773
+ }
1774
+ }
1775
+
1776
+ function ensureNonParallelOrInHelperOrInDescribe(method) {
1777
+ if (parallelLoadingState === 'specs' && !suiteBuilder.inDescribe()) {
1778
+ throw new Error(
1779
+ 'In parallel mode, ' +
1780
+ method +
1781
+ ' must be in a describe block or in a helper file'
1782
+ );
1783
+ }
1784
+ }
1785
+
1786
+ function validateConfigForParallel() {
1787
+ if (!config.random) {
1788
+ throw new Error('Randomization cannot be disabled in parallel mode');
1789
+ }
1790
+
1791
+ if (config.seed !== null && config.seed !== undefined) {
1792
+ throw new Error('Random seed cannot be set in parallel mode');
1793
+ }
1794
+ }
1795
+
1810
1796
  this.describe = function(description, definitionFn) {
1811
1797
  ensureIsNotNested('describe');
1812
1798
  const filename = callerCallerFilename();
@@ -1823,6 +1809,7 @@ getJasmineRequireObj().Env = function(j$) {
1823
1809
 
1824
1810
  this.fdescribe = function(description, definitionFn) {
1825
1811
  ensureIsNotNested('fdescribe');
1812
+ ensureNonParallel('fdescribe');
1826
1813
  const filename = callerCallerFilename();
1827
1814
  return suiteBuilder.fdescribe(description, definitionFn, filename)
1828
1815
  .metadata;
@@ -1864,6 +1851,7 @@ getJasmineRequireObj().Env = function(j$) {
1864
1851
 
1865
1852
  this.fit = function(description, fn, timeout) {
1866
1853
  ensureIsNotNested('fit');
1854
+ ensureNonParallel('fit');
1867
1855
  const filename = callerCallerFilename();
1868
1856
  return suiteBuilder.fit(description, fn, timeout, filename).metadata;
1869
1857
  };
@@ -1937,21 +1925,37 @@ getJasmineRequireObj().Env = function(j$) {
1937
1925
 
1938
1926
  this.beforeEach = function(beforeEachFunction, timeout) {
1939
1927
  ensureIsNotNested('beforeEach');
1928
+ ensureNonParallelOrInHelperOrInDescribe('beforeEach');
1940
1929
  suiteBuilder.beforeEach(beforeEachFunction, timeout);
1941
1930
  };
1942
1931
 
1943
1932
  this.beforeAll = function(beforeAllFunction, timeout) {
1944
1933
  ensureIsNotNested('beforeAll');
1934
+ // This message is -npm-specific, but currently parallel operation is
1935
+ // only supported via -npm.
1936
+ ensureNonParallelOrInDescribe(
1937
+ "In parallel mode, 'beforeAll' " +
1938
+ 'must be in a describe block. Use the globalSetup config ' +
1939
+ 'property for exactly-once setup in parallel mode.'
1940
+ );
1945
1941
  suiteBuilder.beforeAll(beforeAllFunction, timeout);
1946
1942
  };
1947
1943
 
1948
1944
  this.afterEach = function(afterEachFunction, timeout) {
1949
1945
  ensureIsNotNested('afterEach');
1946
+ ensureNonParallelOrInHelperOrInDescribe('afterEach');
1950
1947
  suiteBuilder.afterEach(afterEachFunction, timeout);
1951
1948
  };
1952
1949
 
1953
1950
  this.afterAll = function(afterAllFunction, timeout) {
1954
1951
  ensureIsNotNested('afterAll');
1952
+ // This message is -npm-specific, but currently parallel operation is
1953
+ // only supported via -npm.
1954
+ ensureNonParallelOrInDescribe(
1955
+ "In parallel mode, 'afterAll' " +
1956
+ 'must be in a describe block. Use the globalTeardown config ' +
1957
+ 'property for exactly-once teardown in parallel mode.'
1958
+ );
1955
1959
  suiteBuilder.afterAll(afterAllFunction, timeout);
1956
1960
  };
1957
1961
 
@@ -2006,7 +2010,10 @@ getJasmineRequireObj().Env = function(j$) {
2006
2010
  }
2007
2011
 
2008
2012
  function callerCallerFilename() {
2009
- return new j$.StackTrace(new Error()).frames[3].file;
2013
+ const frames = new j$.StackTrace(new Error()).frames;
2014
+ // frames[3] should always exist except in Jasmine's own tests, which bypass
2015
+ // the global it/describe layer, but don't crash if it doesn't.
2016
+ return frames[3] && frames[3].file;
2010
2017
  }
2011
2018
 
2012
2019
  return Env;
@@ -4005,18 +4012,22 @@ getJasmineRequireObj().GlobalErrors = function(j$) {
4005
4012
  let overrideHandler = null,
4006
4013
  onRemoveOverrideHandler = null;
4007
4014
 
4008
- function onerror(message, source, lineno, colno, error) {
4015
+ function onBrowserError(event) {
4016
+ dispatchBrowserError(event.error, event);
4017
+ }
4018
+
4019
+ function dispatchBrowserError(error, event) {
4009
4020
  if (overrideHandler) {
4010
- overrideHandler(error || message);
4021
+ overrideHandler(error);
4011
4022
  return;
4012
4023
  }
4013
4024
 
4014
4025
  const handler = handlers[handlers.length - 1];
4015
4026
 
4016
4027
  if (handler) {
4017
- handler.apply(null, Array.prototype.slice.call(arguments, 0));
4028
+ handler(error, event);
4018
4029
  } else {
4019
- throw arguments[0];
4030
+ throw error;
4020
4031
  }
4021
4032
  }
4022
4033
 
@@ -4093,8 +4104,7 @@ getJasmineRequireObj().GlobalErrors = function(j$) {
4093
4104
  this.installOne_('uncaughtException', 'Uncaught exception');
4094
4105
  this.installOne_('unhandledRejection', 'Unhandled promise rejection');
4095
4106
  } else {
4096
- const originalHandler = global.onerror;
4097
- global.onerror = onerror;
4107
+ global.addEventListener('error', onBrowserError);
4098
4108
 
4099
4109
  const browserRejectionHandler = function browserRejectionHandler(
4100
4110
  event
@@ -4102,16 +4112,19 @@ getJasmineRequireObj().GlobalErrors = function(j$) {
4102
4112
  if (j$.isError_(event.reason)) {
4103
4113
  event.reason.jasmineMessage =
4104
4114
  'Unhandled promise rejection: ' + event.reason;
4105
- global.onerror(event.reason);
4115
+ dispatchBrowserError(event.reason, event);
4106
4116
  } else {
4107
- global.onerror('Unhandled promise rejection: ' + event.reason);
4117
+ dispatchBrowserError(
4118
+ 'Unhandled promise rejection: ' + event.reason,
4119
+ event
4120
+ );
4108
4121
  }
4109
4122
  };
4110
4123
 
4111
4124
  global.addEventListener('unhandledrejection', browserRejectionHandler);
4112
4125
 
4113
4126
  this.uninstall = function uninstall() {
4114
- global.onerror = originalHandler;
4127
+ global.removeEventListener('error', onBrowserError);
4115
4128
  global.removeEventListener(
4116
4129
  'unhandledrejection',
4117
4130
  browserRejectionHandler
@@ -4120,6 +4133,13 @@ getJasmineRequireObj().GlobalErrors = function(j$) {
4120
4133
  }
4121
4134
  };
4122
4135
 
4136
+ // The listener at the top of the stack will be called with two arguments:
4137
+ // the error and the event. Either of them may be falsy.
4138
+ // The error will normally be provided, but will be falsy in the case of
4139
+ // some browser load-time errors. The event will normally be provided in
4140
+ // browsers but will be falsy in Node.
4141
+ // Listeners that are pushed after spec files have been loaded should be
4142
+ // able to just use the error parameter.
4123
4143
  this.pushListener = function pushListener(listener) {
4124
4144
  handlers.push(listener);
4125
4145
  };
@@ -7089,6 +7109,100 @@ getJasmineRequireObj().NeverSkipPolicy = function(j$) {
7089
7109
  return NeverSkipPolicy;
7090
7110
  };
7091
7111
 
7112
+ getJasmineRequireObj().ParallelReportDispatcher = function(j$) {
7113
+ /**
7114
+ * @class ParallelReportDispatcher
7115
+ * @implements Reporter
7116
+ * @classdesc A report dispatcher packaged for convenient use from outside jasmine-core.
7117
+ *
7118
+ * This is intended to help packages like `jasmine` (the Jasmine runner for
7119
+ * Node.js) do their own report dispatching in order to support parallel
7120
+ * execution. If you aren't implementing a runner package that supports
7121
+ * parallel execution, this class probably isn't what you're looking for.
7122
+ *
7123
+ * Warning: Do not use ParallelReportDispatcher in the same process that
7124
+ * Jasmine specs run in. Doing so will break Jasmine's error handling.
7125
+ * @param onError {function} Function called when an unhandled exception, unhandled promise rejection, or explicit reporter failure occurs
7126
+ */
7127
+ function ParallelReportDispatcher(onError, deps = {}) {
7128
+ const ReportDispatcher = deps.ReportDispatcher || j$.ReportDispatcher;
7129
+ const QueueRunner = deps.QueueRunner || j$.QueueRunner;
7130
+ const globalErrors = deps.globalErrors || new j$.GlobalErrors();
7131
+ const dispatcher = ReportDispatcher(
7132
+ j$.reporterEvents,
7133
+ function(queueRunnerOptions) {
7134
+ queueRunnerOptions = {
7135
+ ...queueRunnerOptions,
7136
+ globalErrors,
7137
+ timeout: { setTimeout, clearTimeout },
7138
+ fail: function(error) {
7139
+ // A callback-style async reporter called either done.fail()
7140
+ // or done(anError).
7141
+ if (!error) {
7142
+ error = new Error('A reporter called done.fail()');
7143
+ }
7144
+
7145
+ onError(error);
7146
+ },
7147
+ onException: function(error) {
7148
+ // A reporter method threw an exception or returned a rejected
7149
+ // promise, or there was an unhandled exception or unhandled promise
7150
+ // rejection while an asynchronous reporter method was running.
7151
+ onError(error);
7152
+ }
7153
+ };
7154
+ new QueueRunner(queueRunnerOptions).execute();
7155
+ },
7156
+ function(error) {
7157
+ // A reporter called done() more than once.
7158
+ onError(error);
7159
+ }
7160
+ );
7161
+
7162
+ const self = {
7163
+ /**
7164
+ * Adds a reporter to the list of reporters that events will be dispatched to.
7165
+ * @function
7166
+ * @name ParallelReportDispatcher#addReporter
7167
+ * @param {Reporter} reporterToAdd The reporter to be added.
7168
+ * @see custom_reporter
7169
+ */
7170
+ addReporter: dispatcher.addReporter.bind(dispatcher),
7171
+ /**
7172
+ * Clears all registered reporters.
7173
+ * @function
7174
+ * @name ParallelReportDispatcher#clearReporters
7175
+ */
7176
+ clearReporters: dispatcher.clearReporters.bind(dispatcher),
7177
+ /**
7178
+ * Installs a global error handler. After this method is called, any
7179
+ * unhandled exceptions or unhandled promise rejections will be passed to
7180
+ * the onError callback that was passed to the constructor.
7181
+ * @function
7182
+ * @name ParallelReportDispatcher#installGlobalErrors
7183
+ */
7184
+ installGlobalErrors: globalErrors.install.bind(globalErrors),
7185
+ /**
7186
+ * Uninstalls the global error handler.
7187
+ * @function
7188
+ * @name ParallelReportDispatcher#uninstallGlobalErrors
7189
+ */
7190
+ uninstallGlobalErrors: function() {
7191
+ // late-bind uninstall because it doesn't exist until install is called
7192
+ globalErrors.uninstall(globalErrors);
7193
+ }
7194
+ };
7195
+
7196
+ for (const eventName of j$.reporterEvents) {
7197
+ self[eventName] = dispatcher[eventName].bind(dispatcher);
7198
+ }
7199
+
7200
+ return self;
7201
+ }
7202
+
7203
+ return ParallelReportDispatcher;
7204
+ };
7205
+
7092
7206
  getJasmineRequireObj().makePrettyPrinter = function(j$) {
7093
7207
  class SinglePrettyPrintRun {
7094
7208
  constructor(customObjectFormatters, pp) {
@@ -7513,15 +7627,11 @@ getJasmineRequireObj().QueueRunner = function(j$) {
7513
7627
  if (typeof this.onComplete !== 'function') {
7514
7628
  throw new Error('invalid onComplete ' + JSON.stringify(this.onComplete));
7515
7629
  }
7516
- this.deprecated = attrs.deprecated;
7517
7630
  }
7518
7631
 
7519
7632
  QueueRunner.prototype.execute = function() {
7520
- this.handleFinalError = (message, source, lineno, colno, error) => {
7521
- // Older browsers would send the error as the first parameter. HTML5
7522
- // specifies the the five parameters above. The error instance should
7523
- // be preffered, otherwise the call stack would get lost.
7524
- this.onException(error || message);
7633
+ this.handleFinalError = error => {
7634
+ this.onException(error);
7525
7635
  };
7526
7636
  this.globalErrors.pushListener(this.handleFinalError);
7527
7637
  this.run(0);
@@ -7710,17 +7820,21 @@ getJasmineRequireObj().QueueRunner = function(j$) {
7710
7820
  // on the stack at this point.
7711
7821
  if (j$.isAsyncFunction_(fn)) {
7712
7822
  this.onException(
7713
- 'An asynchronous before/it/after ' +
7714
- 'function was defined with the async keyword but also took a ' +
7715
- 'done callback. Either remove the done callback (recommended) or ' +
7716
- 'remove the async keyword.'
7823
+ new Error(
7824
+ 'An asynchronous before/it/after ' +
7825
+ 'function was defined with the async keyword but also took a ' +
7826
+ 'done callback. Either remove the done callback (recommended) or ' +
7827
+ 'remove the async keyword.'
7828
+ )
7717
7829
  );
7718
7830
  } else {
7719
7831
  this.onException(
7720
- 'An asynchronous before/it/after ' +
7721
- 'function took a done callback but also returned a promise. ' +
7722
- 'Either remove the done callback (recommended) or change the ' +
7723
- 'function to not return a promise.'
7832
+ new Error(
7833
+ 'An asynchronous before/it/after ' +
7834
+ 'function took a done callback but also returned a promise. ' +
7835
+ 'Either remove the done callback (recommended) or change the ' +
7836
+ 'function to not return a promise.'
7837
+ )
7724
7838
  );
7725
7839
  }
7726
7840
  }
@@ -7820,6 +7934,77 @@ getJasmineRequireObj().ReportDispatcher = function(j$) {
7820
7934
  return ReportDispatcher;
7821
7935
  };
7822
7936
 
7937
+ getJasmineRequireObj().reporterEvents = function() {
7938
+ const events = [
7939
+ /**
7940
+ * `jasmineStarted` is called after all of the specs have been loaded, but just before execution starts.
7941
+ * @function
7942
+ * @name Reporter#jasmineStarted
7943
+ * @param {JasmineStartedInfo} suiteInfo Information about the full Jasmine suite that is being run
7944
+ * @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.
7945
+ * @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion.
7946
+ * @see async
7947
+ */
7948
+ 'jasmineStarted',
7949
+ /**
7950
+ * When the entire suite has finished execution `jasmineDone` is called
7951
+ * @function
7952
+ * @name Reporter#jasmineDone
7953
+ * @param {JasmineDoneInfo} suiteInfo Information about the full Jasmine suite that just finished running.
7954
+ * @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.
7955
+ * @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion.
7956
+ * @see async
7957
+ */
7958
+ 'jasmineDone',
7959
+ /**
7960
+ * `suiteStarted` is invoked when a `describe` starts to run
7961
+ * @function
7962
+ * @name Reporter#suiteStarted
7963
+ * @param {SuiteResult} result Information about the individual {@link describe} being run
7964
+ * @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.
7965
+ * @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion.
7966
+ * @see async
7967
+ */
7968
+ 'suiteStarted',
7969
+ /**
7970
+ * `suiteDone` is invoked when all of the child specs and suites for a given suite have been run
7971
+ *
7972
+ * 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`.
7973
+ * @function
7974
+ * @name Reporter#suiteDone
7975
+ * @param {SuiteResult} result
7976
+ * @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.
7977
+ * @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion.
7978
+ * @see async
7979
+ */
7980
+ 'suiteDone',
7981
+ /**
7982
+ * `specStarted` is invoked when an `it` starts to run (including associated `beforeEach` functions)
7983
+ * @function
7984
+ * @name Reporter#specStarted
7985
+ * @param {SpecResult} result Information about the individual {@link it} being run
7986
+ * @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.
7987
+ * @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion.
7988
+ * @see async
7989
+ */
7990
+ 'specStarted',
7991
+ /**
7992
+ * `specDone` is invoked when an `it` and its associated `beforeEach` and `afterEach` functions have been run.
7993
+ *
7994
+ * 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.
7995
+ * @function
7996
+ * @name Reporter#specDone
7997
+ * @param {SpecResult} result
7998
+ * @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.
7999
+ * @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion.
8000
+ * @see async
8001
+ */
8002
+ 'specDone'
8003
+ ];
8004
+ Object.freeze(events);
8005
+ return events;
8006
+ };
8007
+
7823
8008
  getJasmineRequireObj().interface = function(jasmine, env) {
7824
8009
  const jasmineInterface = {
7825
8010
  /**
@@ -8411,6 +8596,7 @@ getJasmineRequireObj().Runner = function(j$) {
8411
8596
  class Runner {
8412
8597
  constructor(options) {
8413
8598
  this.topSuite_ = options.topSuite;
8599
+ // TODO use names that read like getters
8414
8600
  this.totalSpecsDefined_ = options.totalSpecsDefined;
8415
8601
  this.focusedRunables_ = options.focusedRunables;
8416
8602
  this.runableResources_ = options.runableResources;
@@ -8435,11 +8621,11 @@ getJasmineRequireObj().Runner = function(j$) {
8435
8621
  ];
8436
8622
  }
8437
8623
 
8438
- // Although execute returns a promise, it isn't async for backwards
8439
- // compatibility: The "Invalid order" exception needs to be propagated
8440
- // synchronously from Env#execute.
8441
- // TODO: make this and Env#execute async in the next major release
8442
- execute(runablesToRun) {
8624
+ parallelReset() {
8625
+ this.executedBefore_ = false;
8626
+ }
8627
+
8628
+ async execute(runablesToRun) {
8443
8629
  if (this.executedBefore_) {
8444
8630
  this.topSuite_.reset();
8445
8631
  }
@@ -8535,13 +8721,17 @@ getJasmineRequireObj().Runner = function(j$) {
8535
8721
  /**
8536
8722
  * Information passed to the {@link Reporter#jasmineStarted} event.
8537
8723
  * @typedef JasmineStartedInfo
8538
- * @property {Int} totalSpecsDefined - The total number of specs defined in this suite.
8539
- * @property {Order} order - Information about the ordering (random or not) of this execution of the suite.
8724
+ * @property {Int} totalSpecsDefined - The total number of specs defined in this suite. Note that this property is not present when Jasmine is run in parallel mode.
8725
+ * @property {Order} order - Information about the ordering (random or not) of this execution of the suite. Note that this property is not present when Jasmine is run in parallel mode.
8726
+ * @property {Boolean} parallel - Whether Jasmine is being run in parallel mode.
8540
8727
  * @since 2.0.0
8541
8728
  */
8542
8729
  await this.reporter_.jasmineStarted({
8730
+ // In parallel mode, the jasmineStarted event is separately dispatched
8731
+ // by jasmine-npm. This event only reaches reporters in non-parallel.
8543
8732
  totalSpecsDefined,
8544
- order: order
8733
+ order: order,
8734
+ parallel: false
8545
8735
  });
8546
8736
 
8547
8737
  this.currentlyExecutingSuites_.push(this.topSuite_);
@@ -8553,7 +8743,7 @@ getJasmineRequireObj().Runner = function(j$) {
8553
8743
 
8554
8744
  this.runableResources_.clearForRunable(this.topSuite_.id);
8555
8745
  this.currentlyExecutingSuites_.pop();
8556
- let overallStatus, incompleteReason;
8746
+ let overallStatus, incompleteReason, incompleteCode;
8557
8747
 
8558
8748
  if (
8559
8749
  this.hasFailures ||
@@ -8563,9 +8753,11 @@ getJasmineRequireObj().Runner = function(j$) {
8563
8753
  } else if (this.focusedRunables_().length > 0) {
8564
8754
  overallStatus = 'incomplete';
8565
8755
  incompleteReason = 'fit() or fdescribe() was found';
8756
+ incompleteCode = 'focused';
8566
8757
  } else if (totalSpecsDefined === 0) {
8567
8758
  overallStatus = 'incomplete';
8568
8759
  incompleteReason = 'No specs found';
8760
+ incompleteCode = 'noSpecsFound';
8569
8761
  } else {
8570
8762
  overallStatus = 'passed';
8571
8763
  }
@@ -8575,8 +8767,10 @@ getJasmineRequireObj().Runner = function(j$) {
8575
8767
  * @typedef JasmineDoneInfo
8576
8768
  * @property {OverallStatus} overallStatus - The overall result of the suite: 'passed', 'failed', or 'incomplete'.
8577
8769
  * @property {Int} totalTime - The total time (in ms) that it took to execute the suite
8578
- * @property {IncompleteReason} incompleteReason - Explanation of why the suite was incomplete.
8579
- * @property {Order} order - Information about the ordering (random or not) of this execution of the suite.
8770
+ * @property {String} incompleteReason - Human-readable explanation of why the suite was incomplete.
8771
+ * @property {String} incompleteCode - Machine-readable explanation of why the suite was incomplete: 'focused', 'noSpecsFound', or undefined.
8772
+ * @property {Order} order - Information about the ordering (random or not) of this execution of the suite. Note that this property is not present when Jasmine is run in parallel mode.
8773
+ * @property {Int} numWorkers - Number of parallel workers. Note that this property is only present when Jasmine is run in parallel mode.
8580
8774
  * @property {Expectation[]} failedExpectations - List of expectations that failed in an {@link afterAll} at the global level.
8581
8775
  * @property {Expectation[]} deprecationWarnings - List of deprecation warnings that occurred at the global level.
8582
8776
  * @since 2.4.0
@@ -8585,6 +8779,7 @@ getJasmineRequireObj().Runner = function(j$) {
8585
8779
  overallStatus: overallStatus,
8586
8780
  totalTime: jasmineTimer.elapsed(),
8587
8781
  incompleteReason: incompleteReason,
8782
+ incompleteCode: incompleteCode,
8588
8783
  order: order,
8589
8784
  failedExpectations: this.topSuite_.result.failedExpectations,
8590
8785
  deprecationWarnings: this.topSuite_.result.deprecationWarnings
@@ -9670,6 +9865,10 @@ getJasmineRequireObj().Suite = function(j$) {
9670
9865
  this.reportedDone = false;
9671
9866
  };
9672
9867
 
9868
+ Suite.prototype.removeChildren = function() {
9869
+ this.children = [];
9870
+ };
9871
+
9673
9872
  Suite.prototype.addChild = function(child) {
9674
9873
  this.children.push(child);
9675
9874
  };
@@ -9885,6 +10084,17 @@ getJasmineRequireObj().SuiteBuilder = function(j$) {
9885
10084
  this.focusedRunables = [];
9886
10085
  }
9887
10086
 
10087
+ inDescribe() {
10088
+ return this.currentDeclarationSuite_ !== this.topSuite;
10089
+ }
10090
+
10091
+ parallelReset() {
10092
+ this.topSuite.removeChildren();
10093
+ this.topSuite.reset();
10094
+ this.totalSpecsDefined = 0;
10095
+ this.focusedRunables = [];
10096
+ }
10097
+
9888
10098
  describe(description, definitionFn, filename) {
9889
10099
  ensureIsFunction(definitionFn, 'describe');
9890
10100
  const suite = this.suiteFactory_(description, filename);
@@ -10182,16 +10392,35 @@ getJasmineRequireObj().Timer = function() {
10182
10392
  };
10183
10393
  })(Date);
10184
10394
 
10395
+ /**
10396
+ * @class Timer
10397
+ * @classdesc Tracks elapsed time
10398
+ * @example
10399
+ * const timer = new jasmine.Timer();
10400
+ * timer.start();
10401
+ * const elapsed = timer.elapsed()
10402
+ */
10185
10403
  function Timer(options) {
10186
10404
  options = options || {};
10187
10405
 
10188
10406
  const now = options.now || defaultNow;
10189
10407
  let startTime;
10190
10408
 
10409
+ /**
10410
+ * Starts the timer.
10411
+ * @function
10412
+ * @name Timer#start
10413
+ */
10191
10414
  this.start = function() {
10192
10415
  startTime = now();
10193
10416
  };
10194
10417
 
10418
+ /**
10419
+ * Determines the time since the timer was started.
10420
+ * @function
10421
+ * @name Timer#elapsed
10422
+ * @returns {number} Elapsed time in milliseconds, or NaN if the timer has not been started
10423
+ */
10195
10424
  this.elapsed = function() {
10196
10425
  return now() - startTime;
10197
10426
  };
@@ -10484,5 +10713,5 @@ getJasmineRequireObj().UserContext = function(j$) {
10484
10713
  };
10485
10714
 
10486
10715
  getJasmineRequireObj().version = function() {
10487
- return '4.6.0';
10716
+ return '5.0.0-alpha.1';
10488
10717
  };
@@ -6,36 +6,48 @@
6
6
  const jasmineRequire = require('./jasmine-core/jasmine.js');
7
7
  module.exports = jasmineRequire;
8
8
 
9
+ const bootOnce = (function() {
10
+ let jasmine, jasmineInterface;
11
+
12
+ return function bootWithoutGlobals() {
13
+ if (!jasmineInterface) {
14
+ jasmine = jasmineRequire.core(jasmineRequire);
15
+ const env = jasmine.getEnv({ suppressLoadErrors: true });
16
+ jasmineInterface = jasmineRequire.interface(jasmine, env);
17
+ }
18
+
19
+ return {jasmine, jasmineInterface};
20
+ };
21
+ }());
22
+
9
23
  /**
10
24
  * Boots a copy of Jasmine and returns an object as described in {@link jasmine}.
25
+ * If boot is called multiple times, the same object is returned every time.
11
26
  * @type {function}
12
27
  * @return {jasmine}
13
28
  */
14
- module.exports.boot = require('./jasmine-core/node_boot.js');
29
+ module.exports.boot = function() {
30
+ const {jasmine, jasmineInterface} = bootOnce();
31
+
32
+ for (const k in jasmineInterface) {
33
+ global[k] = jasmineInterface[k];
34
+ }
35
+
36
+ return jasmine;
37
+ };
15
38
 
16
39
  /**
17
40
  * Boots a copy of Jasmine and returns an object containing the properties
18
41
  * that would normally be added to the global object. If noGlobals is called
19
42
  * multiple times, the same object is returned every time.
20
43
  *
21
- * Do not call boot() if you also call noGlobals().
22
- *
23
44
  * @example
24
45
  * const {describe, beforeEach, it, expect, jasmine} = require('jasmine-core').noGlobals();
25
46
  */
26
- module.exports.noGlobals = (function() {
27
- let jasmineInterface;
28
-
29
- return function bootWithoutGlobals() {
30
- if (!jasmineInterface) {
31
- const jasmine = jasmineRequire.core(jasmineRequire);
32
- const env = jasmine.getEnv({ suppressLoadErrors: true });
33
- jasmineInterface = jasmineRequire.interface(jasmine, env);
34
- }
35
-
36
- return jasmineInterface;
37
- };
38
- }());
47
+ module.exports.noGlobals = function() {
48
+ const {jasmineInterface} = bootOnce();
49
+ return jasmineInterface;
50
+ };
39
51
 
40
52
  const path = require('path'),
41
53
  fs = require('fs');
@@ -43,10 +55,9 @@ const path = require('path'),
43
55
  const rootPath = path.join(__dirname, 'jasmine-core'),
44
56
  bootFiles = ['boot0.js', 'boot1.js'],
45
57
  legacyBootFiles = ['boot.js'],
46
- nodeBootFiles = ['node_boot.js'],
47
58
  cssFiles = [],
48
59
  jsFiles = [],
49
- jsFilesToSkip = ['jasmine.js'].concat(bootFiles, legacyBootFiles, nodeBootFiles);
60
+ jsFilesToSkip = ['jasmine.js'].concat(bootFiles, legacyBootFiles);
50
61
 
51
62
  fs.readdirSync(rootPath).forEach(function(file) {
52
63
  if(fs.statSync(path.join(rootPath, file)).isFile()) {
@@ -56,18 +67,18 @@ fs.readdirSync(rootPath).forEach(function(file) {
56
67
  break;
57
68
  case '.js':
58
69
  if (jsFilesToSkip.indexOf(file) < 0) {
59
- jsFiles.push(file);
60
- }
70
+ jsFiles.push(file);
71
+ }
61
72
  break;
62
73
  }
63
74
  }
64
75
  });
65
76
 
66
77
  module.exports.files = {
78
+ self: __filename,
67
79
  path: rootPath,
68
80
  bootDir: rootPath,
69
81
  bootFiles: bootFiles,
70
- nodeBootFiles: nodeBootFiles,
71
82
  cssFiles: cssFiles,
72
83
  jsFiles: ['jasmine.js'].concat(jsFiles),
73
84
  imagesDir: path.join(__dirname, '../images')
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "jasmine-core",
3
3
  "license": "MIT",
4
- "version": "4.6.0",
4
+ "version": "5.0.0-alpha.1",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "https://github.com/jasmine/jasmine.git"
@@ -34,21 +34,21 @@
34
34
  "package.json"
35
35
  ],
36
36
  "devDependencies": {
37
- "eslint": "^7.32.0",
38
- "eslint-plugin-compat": ">=4.0.0 <4.1.0",
39
- "glob": "^7.2.0",
40
- "grunt": ">=1.0.4 <1.6.0",
37
+ "eslint": "^8.36.0",
38
+ "eslint-plugin-compat": "^4.0.0",
39
+ "glob": "^9.3.1",
40
+ "grunt": "^1.0.4",
41
41
  "grunt-cli": "^1.3.2",
42
42
  "grunt-contrib-compress": "^2.0.0",
43
43
  "grunt-contrib-concat": "^2.0.0",
44
44
  "grunt-css-url-embed": "^1.11.1",
45
45
  "grunt-sass": "^3.0.2",
46
- "jasmine": "^4.1.0",
46
+ "jasmine": "github:jasmine/jasmine-npm#5.0",
47
47
  "jasmine-browser-runner": "^1.0.0",
48
- "jsdom": "^19.0.0",
48
+ "jsdom": "^21.1.1",
49
49
  "load-grunt-tasks": "^5.1.0",
50
50
  "prettier": "1.17.1",
51
- "sass": "1.58.3",
51
+ "sass": "^1.58.3",
52
52
  "shelljs": "^0.8.3",
53
53
  "temp": "^0.9.0"
54
54
  },
@@ -101,10 +101,9 @@
101
101
  }
102
102
  },
103
103
  "browserslist": [
104
- "Safari >= 14",
104
+ "Safari >= 15",
105
+ "Firefox >= 102",
105
106
  "last 2 Chrome versions",
106
- "last 2 Firefox versions",
107
- "Firefox >= 91",
108
107
  "last 2 Edge versions"
109
108
  ]
110
109
  }
@@ -1,38 +0,0 @@
1
- /*
2
- Copyright (c) 2008-2023 Pivotal Labs
3
-
4
- Permission is hereby granted, free of charge, to any person obtaining
5
- a copy of this software and associated documentation files (the
6
- "Software"), to deal in the Software without restriction, including
7
- without limitation the rights to use, copy, modify, merge, publish,
8
- distribute, sublicense, and/or sell copies of the Software, and to
9
- permit persons to whom the Software is furnished to do so, subject to
10
- the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be
13
- included in all copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
- */
23
- module.exports = function(jasmineRequire) {
24
- const jasmine = jasmineRequire.core(jasmineRequire);
25
-
26
- const env = jasmine.getEnv({ suppressLoadErrors: true });
27
-
28
- const jasmineInterface = jasmineRequire.interface(jasmine, env);
29
-
30
- extend(global, jasmineInterface);
31
-
32
- function extend(destination, source) {
33
- for (const property in source) destination[property] = source[property];
34
- return destination;
35
- }
36
-
37
- return jasmine;
38
- };