jasmine-core 6.0.0-alpha.1 → 6.0.0-alpha.2

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
@@ -30,7 +30,7 @@ Microsoft Edge) as well as Node.
30
30
  | Environment | Supported versions |
31
31
  |-------------------|----------------------------------|
32
32
  | Node | 20, 22, 24 |
33
- | Safari | 16*, 17* |
33
+ | Safari | 16*, 17*, 26* |
34
34
  | Chrome | Evergreen |
35
35
  | Firefox | Evergreen, 102*, 115*, 128*, 140 |
36
36
  | Edge | Evergreen |
@@ -58,6 +58,12 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
58
58
  */
59
59
  env.addReporter(jsApiReporter);
60
60
  env.addReporter(htmlReporter);
61
+ /**
62
+ * Configures Jasmine based on the current set of query parameters. This
63
+ * supports all parameters set by the HTML reporter as well as
64
+ * spec=partialPath, which filters out specs whose paths don't contain the
65
+ * parameter.
66
+ */
61
67
  env.configure(urls.configFromCurrentUrl());
62
68
 
63
69
  /**
@@ -35,6 +35,8 @@ jasmineRequire.html = function(j$) {
35
35
  j$.private.SymbolsView = jasmineRequire.SymbolsView(j$);
36
36
  j$.private.SummaryTreeView = jasmineRequire.SummaryTreeView(j$);
37
37
  j$.private.FailuresView = jasmineRequire.FailuresView(j$);
38
+ j$.private.PerformanceView = jasmineRequire.PerformanceView(j$);
39
+ j$.private.TabBar = jasmineRequire.TabBar(j$);
38
40
  j$.HtmlReporter = jasmineRequire.HtmlReporter(j$);
39
41
  j$.HtmlReporterV2Urls = jasmineRequire.HtmlReporterV2Urls(j$);
40
42
  j$.HtmlReporterV2 = jasmineRequire.HtmlReporterV2(j$);
@@ -187,16 +189,52 @@ jasmineRequire.HtmlReporter = function(j$) {
187
189
  results.appendChild(summary.rootEl);
188
190
 
189
191
  if (this.#stateBuilder.anyNonTopSuiteFailures) {
190
- this.#alerts.addFailureToggle(
191
- () => this.#setMenuModeTo('jasmine-failure-list'),
192
- () => this.#setMenuModeTo('jasmine-spec-list')
193
- );
194
-
192
+ this.#addFailureToggle();
195
193
  this.#setMenuModeTo('jasmine-failure-list');
196
194
  this.#failures.show();
197
195
  }
198
196
  }
199
197
 
198
+ #addFailureToggle() {
199
+ const onClickFailures = () => this.#setMenuModeTo('jasmine-failure-list');
200
+ const onClickSpecList = () => this.#setMenuModeTo('jasmine-spec-list');
201
+ const failuresLink = createDom(
202
+ 'a',
203
+ { className: 'jasmine-failures-menu', href: '#' },
204
+ 'Failures'
205
+ );
206
+ let specListLink = createDom(
207
+ 'a',
208
+ { className: 'jasmine-spec-list-menu', href: '#' },
209
+ 'Spec List'
210
+ );
211
+
212
+ failuresLink.onclick = function() {
213
+ onClickFailures();
214
+ return false;
215
+ };
216
+
217
+ specListLink.onclick = function() {
218
+ onClickSpecList();
219
+ return false;
220
+ };
221
+
222
+ this.#alerts.addBar(
223
+ createDom(
224
+ 'span',
225
+ { className: 'jasmine-menu jasmine-bar jasmine-spec-list' },
226
+ [createDom('span', {}, 'Spec List | '), failuresLink]
227
+ )
228
+ );
229
+ this.#alerts.addBar(
230
+ createDom(
231
+ 'span',
232
+ { className: 'jasmine-menu jasmine-bar jasmine-failure-list' },
233
+ [specListLink, createDom('span', {}, ' | Failures ')]
234
+ )
235
+ );
236
+ }
237
+
200
238
  #find(selector) {
201
239
  return this.#getContainer().querySelector(
202
240
  '.jasmine_html-reporter ' + selector
@@ -434,6 +472,7 @@ jasmineRequire.AlertsView = function(j$) {
434
472
  );
435
473
  }
436
474
 
475
+ // TODO: remove this once HtmlReporterV2 doesn't use it
437
476
  addFailureToggle(onClickFailures, onClickSpecList) {
438
477
  const failuresLink = createDom(
439
478
  'a',
@@ -456,14 +495,20 @@ jasmineRequire.AlertsView = function(j$) {
456
495
  return false;
457
496
  };
458
497
 
459
- this.#createAndAdd('jasmine-menu jasmine-bar jasmine-spec-list', [
460
- createDom('span', {}, 'Spec List | '),
461
- failuresLink
462
- ]);
463
- this.#createAndAdd('jasmine-menu jasmine-bar jasmine-failure-list', [
464
- specListLink,
465
- createDom('span', {}, ' | Failures ')
466
- ]);
498
+ this.rootEl.appendChild(
499
+ createDom(
500
+ 'span',
501
+ { className: 'jasmine-menu jasmine-bar jasmine-spec-list' },
502
+ [createDom('span', {}, 'Spec List | '), failuresLink]
503
+ )
504
+ );
505
+ this.rootEl.appendChild(
506
+ createDom(
507
+ 'span',
508
+ { className: 'jasmine-menu jasmine-bar jasmine-failure-list' },
509
+ [specListLink, createDom('span', {}, ' | Failures ')]
510
+ )
511
+ );
467
512
  }
468
513
 
469
514
  addGlobalFailure(failure) {
@@ -946,6 +991,10 @@ jasmineRequire.HtmlReporterV2 = function(j$) {
946
991
 
947
992
  const { createDom, noExpectations } = j$.private.htmlReporterUtils;
948
993
 
994
+ const specListTabId = 'jasmine-specListTab';
995
+ const failuresTabId = 'jasmine-failuresTab';
996
+ const perfTabId = 'jasmine-perfTab';
997
+
949
998
  /**
950
999
  * @class HtmlReporterV2
951
1000
  * @classdesc Displays results and allows re-running individual specs and suites.
@@ -958,7 +1007,7 @@ jasmineRequire.HtmlReporterV2 = function(j$) {
958
1007
  * const reporter = new jasmine.HtmlReporterV2({
959
1008
  * env,
960
1009
  * urls,
961
- * container: document.body
1010
+ * getContainer: () => document.body
962
1011
  * });
963
1012
  */
964
1013
  class HtmlReporterV2 {
@@ -974,6 +1023,7 @@ jasmineRequire.HtmlReporterV2 = function(j$) {
974
1023
  // Sub-views
975
1024
  #alerts;
976
1025
  #statusBar;
1026
+ #tabBar;
977
1027
  #progress;
978
1028
  #banner;
979
1029
  #failures;
@@ -1011,6 +1061,25 @@ jasmineRequire.HtmlReporterV2 = function(j$) {
1011
1061
  this.#statusBar = new j$.private.OverallStatusBar(this.#urlBuilder);
1012
1062
  this.#statusBar.showRunning();
1013
1063
  this.#alerts.addBar(this.#statusBar.rootEl);
1064
+
1065
+ this.#tabBar = new j$.private.TabBar(
1066
+ [
1067
+ { id: specListTabId, label: 'Spec List' },
1068
+ { id: failuresTabId, label: 'Failures' },
1069
+ { id: perfTabId, label: 'Performance' }
1070
+ ],
1071
+ tabId => {
1072
+ if (tabId === specListTabId) {
1073
+ this.#setMenuModeTo('jasmine-spec-list');
1074
+ } else if (tabId === failuresTabId) {
1075
+ this.#setMenuModeTo('jasmine-failure-list');
1076
+ } else {
1077
+ this.#setMenuModeTo('jasmine-performance');
1078
+ }
1079
+ }
1080
+ );
1081
+ this.#alerts.addBar(this.#tabBar.rootEl);
1082
+
1014
1083
  this.#progress = new ProgressView();
1015
1084
  this.#banner = new j$.private.Banner(
1016
1085
  this.#queryString.navigateWithNewParam.bind(this.#queryString),
@@ -1101,15 +1170,17 @@ jasmineRequire.HtmlReporterV2 = function(j$) {
1101
1170
  );
1102
1171
  summary.addResults(this.#stateBuilder.topResults);
1103
1172
  results.appendChild(summary.rootEl);
1173
+ const perf = new j$.private.PerformanceView();
1174
+ perf.addResults(this.#stateBuilder.topResults);
1175
+ results.appendChild(perf.rootEl);
1176
+ this.#tabBar.showTab(specListTabId);
1177
+ this.#tabBar.showTab(perfTabId);
1104
1178
 
1105
1179
  if (this.#stateBuilder.anyNonTopSuiteFailures) {
1106
- this.#alerts.addFailureToggle(
1107
- () => this.#setMenuModeTo('jasmine-failure-list'),
1108
- () => this.#setMenuModeTo('jasmine-spec-list')
1109
- );
1110
-
1111
- this.#setMenuModeTo('jasmine-failure-list');
1112
- this.#failures.show();
1180
+ this.#tabBar.showTab(failuresTabId);
1181
+ this.#tabBar.selectTab(failuresTabId);
1182
+ } else {
1183
+ this.#tabBar.selectTab(specListTabId);
1113
1184
  }
1114
1185
  }
1115
1186
 
@@ -1148,7 +1219,6 @@ jasmineRequire.HtmlReporterV2 = function(j$) {
1148
1219
  this.rootEl.value = this.rootEl.value + 1;
1149
1220
 
1150
1221
  if (result.status === 'failed') {
1151
- // TODO: also a non-color indicator
1152
1222
  this.rootEl.classList.add('failed');
1153
1223
  }
1154
1224
  }
@@ -1233,7 +1303,10 @@ jasmineRequire.HtmlReporterV2Urls = function(j$) {
1233
1303
  }
1234
1304
 
1235
1305
  /**
1236
- * Creates a {@link Configuration} from the current page's URL.
1306
+ * Creates a {@link Configuration} from the current page's URL. Supported
1307
+ * query string parameters include all those set by {@link HtmlReporterV2}
1308
+ * as well as spec=partialPath, which filters out specs whose paths don't
1309
+ * contain partialPath.
1237
1310
  * @returns {Configuration}
1238
1311
  * @example
1239
1312
  * const urls = new jasmine.HtmlReporterV2Urls();
@@ -1259,9 +1332,10 @@ jasmineRequire.HtmlReporterV2Urls = function(j$) {
1259
1332
  }
1260
1333
 
1261
1334
  const specFilter = new j$.private.HtmlSpecFilterV2({
1262
- filterString: () => {
1263
- return this.queryString.getParam('path');
1264
- }
1335
+ filterParams: () => ({
1336
+ path: this.queryString.getParam('path'),
1337
+ spec: this.queryString.getParam('spec')
1338
+ })
1265
1339
  });
1266
1340
 
1267
1341
  config.specFilter = function(spec) {
@@ -1281,35 +1355,35 @@ jasmineRequire.HtmlReporterV2Urls = function(j$) {
1281
1355
 
1282
1356
  jasmineRequire.HtmlSpecFilterV2 = function() {
1283
1357
  class HtmlSpecFilterV2 {
1284
- #getFilterString;
1358
+ #getFilterParams;
1285
1359
 
1286
1360
  constructor(options) {
1287
- this.#getFilterString = options.filterString;
1361
+ this.#getFilterParams = options.filterParams;
1288
1362
  }
1289
1363
 
1290
- /**
1291
- * Determines whether the spec with the specified name should be executed.
1292
- * @name HtmlSpecFilterV2#matches
1293
- * @function
1294
- * @param {Spec} spec
1295
- * @returns {boolean}
1296
- */
1297
1364
  matches(spec) {
1298
- const filterString = this.#getFilterString();
1299
-
1300
- if (!filterString) {
1301
- return true;
1365
+ const params = this.#getFilterParams();
1366
+
1367
+ if (params.path) {
1368
+ return this.#matchesPath(spec, JSON.parse(params.path));
1369
+ } else if (params.spec) {
1370
+ // Like legacy HtmlSpecFilter, retained because it's convenient for
1371
+ // hand-constructing filter URLs
1372
+ return spec.getFullName().includes(params.spec);
1302
1373
  }
1303
1374
 
1304
- const filterPath = JSON.parse(this.#getFilterString());
1375
+ return true;
1376
+ }
1377
+
1378
+ #matchesPath(spec, path) {
1305
1379
  const specPath = spec.getPath();
1306
1380
 
1307
- if (filterPath.length > specPath.length) {
1381
+ if (path.length > specPath.length) {
1308
1382
  return false;
1309
1383
  }
1310
1384
 
1311
- for (let i = 0; i < filterPath.length; i++) {
1312
- if (specPath[i] !== filterPath[i]) {
1385
+ for (let i = 0; i < path.length; i++) {
1386
+ if (specPath[i] !== path[i]) {
1313
1387
  return false;
1314
1388
  }
1315
1389
  }
@@ -1430,6 +1504,105 @@ jasmineRequire.OverallStatusBar = function(j$) {
1430
1504
  return OverallStatusBar;
1431
1505
  };
1432
1506
 
1507
+ jasmineRequire.PerformanceView = function(j$) {
1508
+ const createDom = j$.private.htmlReporterUtils.createDom;
1509
+ const MAX_SLOW_SPECS = 20;
1510
+
1511
+ class PerformanceView {
1512
+ #summary;
1513
+ #tbody;
1514
+
1515
+ constructor() {
1516
+ this.#tbody = document.createElement('tbody');
1517
+ this.#summary = document.createElement('div');
1518
+ this.rootEl = createDom(
1519
+ 'div',
1520
+ { className: 'jasmine-performance-view' },
1521
+ createDom('h2', {}, 'Performance'),
1522
+ this.#summary,
1523
+ createDom('h3', {}, 'Slowest Specs'),
1524
+ createDom(
1525
+ 'table',
1526
+ {},
1527
+ createDom(
1528
+ 'thead',
1529
+ {},
1530
+ createDom(
1531
+ 'tr',
1532
+ {},
1533
+ createDom('th', {}, 'Duration'),
1534
+ createDom('th', {}, 'Spec Name')
1535
+ )
1536
+ ),
1537
+ this.#tbody
1538
+ )
1539
+ );
1540
+ }
1541
+
1542
+ addResults(resultsTree) {
1543
+ const specResults = [];
1544
+ getSpecResults(resultsTree, specResults);
1545
+
1546
+ if (specResults.length === 0) {
1547
+ return;
1548
+ }
1549
+
1550
+ specResults.sort(function(a, b) {
1551
+ if (a.duration < b.duration) {
1552
+ return 1;
1553
+ } else if (a.duration > b.duration) {
1554
+ return -1;
1555
+ } else {
1556
+ return 0;
1557
+ }
1558
+ });
1559
+
1560
+ this.#populateSumary(specResults);
1561
+ this.#populateTable(specResults);
1562
+ }
1563
+
1564
+ #populateSumary(specResults) {
1565
+ const total = specResults.map(r => r.duration).reduce((a, b) => a + b, 0);
1566
+ const mean = total / specResults.length;
1567
+ const median = specResults[Math.floor(specResults.length / 2)].duration;
1568
+ this.#summary.appendChild(
1569
+ document.createTextNode(`Mean spec run time: ${mean.toFixed(0)}ms`)
1570
+ );
1571
+ this.#summary.appendChild(document.createElement('br'));
1572
+ this.#summary.appendChild(
1573
+ document.createTextNode(`Median spec run time: ${median}ms`)
1574
+ );
1575
+ }
1576
+
1577
+ #populateTable(specResults) {
1578
+ specResults = specResults.slice(0, MAX_SLOW_SPECS);
1579
+
1580
+ for (const r of specResults) {
1581
+ this.#tbody.appendChild(
1582
+ createDom(
1583
+ 'tr',
1584
+ {},
1585
+ createDom('td', {}, `${r.duration}ms`),
1586
+ createDom('td', {}, r.fullName)
1587
+ )
1588
+ );
1589
+ }
1590
+ }
1591
+ }
1592
+
1593
+ function getSpecResults(resultsTree, dest) {
1594
+ for (const node of resultsTree.children) {
1595
+ if (node.type === 'suite') {
1596
+ getSpecResults(node, dest);
1597
+ } else if (node.result.status !== 'excluded') {
1598
+ dest.push(node.result);
1599
+ }
1600
+ }
1601
+ }
1602
+
1603
+ return PerformanceView;
1604
+ };
1605
+
1433
1606
  jasmineRequire.ResultsStateBuilder = function(j$) {
1434
1607
  'use strict';
1435
1608
 
@@ -1661,3 +1834,81 @@ jasmineRequire.SymbolsView = function(j$) {
1661
1834
 
1662
1835
  return SymbolsView;
1663
1836
  };
1837
+
1838
+ jasmineRequire.TabBar = function(j$) {
1839
+ const createDom = j$.private.htmlReporterUtils.createDom;
1840
+
1841
+ class TabBar {
1842
+ #tabs;
1843
+ #onSelectTab;
1844
+
1845
+ // tabSpecs should be an array of {id, label}.
1846
+ // All tabs are initially not visible and not selected.
1847
+ constructor(tabSpecs, onSelectTab) {
1848
+ this.#onSelectTab = onSelectTab;
1849
+ this.#tabs = [];
1850
+ this.#tabs = tabSpecs.map(ts => new Tab(ts, () => this.selectTab(ts.id)));
1851
+
1852
+ this.rootEl = createDom(
1853
+ 'span',
1854
+ { className: 'jasmine-menu jasmine-bar' },
1855
+ this.#tabs.map(t => t.rootEl)
1856
+ );
1857
+ }
1858
+
1859
+ showTab(id) {
1860
+ for (const tab of this.#tabs) {
1861
+ if (tab.rootEl.id === id) {
1862
+ tab.setVisibility(true);
1863
+ }
1864
+ }
1865
+ }
1866
+
1867
+ selectTab(id) {
1868
+ for (const tab of this.#tabs) {
1869
+ tab.setSelected(tab.rootEl.id === id);
1870
+ }
1871
+
1872
+ this.#onSelectTab(id);
1873
+ }
1874
+ }
1875
+
1876
+ class Tab {
1877
+ #spec;
1878
+ #onClick;
1879
+
1880
+ constructor(spec, onClick) {
1881
+ this.#spec = spec;
1882
+ this.#onClick = onClick;
1883
+ this.rootEl = createDom(
1884
+ 'span',
1885
+ { id: spec.id, className: 'jasmine-tab jasmine-hidden' },
1886
+ this.#createLink()
1887
+ );
1888
+ }
1889
+
1890
+ setVisibility(visible) {
1891
+ this.rootEl.classList.toggle('jasmine-hidden', !visible);
1892
+ }
1893
+
1894
+ setSelected(selected) {
1895
+ if (selected) {
1896
+ this.rootEl.textContent = this.#spec.label;
1897
+ } else {
1898
+ this.rootEl.textContent = '';
1899
+ this.rootEl.appendChild(this.#createLink());
1900
+ }
1901
+ }
1902
+
1903
+ #createLink() {
1904
+ const link = createDom('a', { href: '#' }, this.#spec.label);
1905
+ link.addEventListener('click', e => {
1906
+ e.preventDefault();
1907
+ this.#onClick();
1908
+ });
1909
+ return link;
1910
+ }
1911
+ }
1912
+
1913
+ return TabBar;
1914
+ };
@@ -8,7 +8,7 @@ body {
8
8
  background-color: #eee;
9
9
  padding: 5px;
10
10
  margin: -8px;
11
- font-size: 11px;
11
+ font-size: 12px;
12
12
  font-family: Monaco, "Lucida Console", monospace;
13
13
  line-height: 14px;
14
14
  color: #333;
@@ -63,7 +63,7 @@ body {
63
63
  float: right;
64
64
  line-height: 28px;
65
65
  padding-right: 9px;
66
- font-size: 11px;
66
+ font-size: 12px;
67
67
  }
68
68
  .jasmine_html-reporter .jasmine-symbol-summary {
69
69
  overflow: hidden;
@@ -198,11 +198,17 @@ body {
198
198
  color: white;
199
199
  }
200
200
  .jasmine_html-reporter.jasmine-spec-list .jasmine-bar.jasmine-menu.jasmine-failure-list,
201
- .jasmine_html-reporter.jasmine-spec-list .jasmine-results .jasmine-failures {
201
+ .jasmine_html-reporter.jasmine-spec-list .jasmine-results .jasmine-failures,
202
+ .jasmine_html-reporter.jasmine-spec-list .jasmine-performance-view {
202
203
  display: none;
203
204
  }
204
205
  .jasmine_html-reporter.jasmine-failure-list .jasmine-bar.jasmine-menu.jasmine-spec-list,
205
- .jasmine_html-reporter.jasmine-failure-list .jasmine-summary {
206
+ .jasmine_html-reporter.jasmine-failure-list .jasmine-summary,
207
+ .jasmine_html-reporter.jasmine-failure-list .jasmine-performance-view {
208
+ display: none;
209
+ }
210
+ .jasmine_html-reporter.jasmine-performance .jasmine-results .jasmine-failures,
211
+ .jasmine_html-reporter.jasmine-performance .jasmine-summary {
206
212
  display: none;
207
213
  }
208
214
  .jasmine_html-reporter .jasmine-results {
@@ -323,4 +329,23 @@ body {
323
329
  }
324
330
  .jasmine_html-reporter .jasmine-debug-log .jasmine-debug-log-msg {
325
331
  white-space: pre;
332
+ }
333
+
334
+ .jasmine-hidden {
335
+ display: none;
336
+ }
337
+
338
+ .jasmine-tab + .jasmine-tab:before {
339
+ content: " | ";
340
+ }
341
+
342
+ .jasmine-performance-view h2, .jasmine-performance-view h3 {
343
+ margin-top: 1em;
344
+ margin-bottom: 1em;
345
+ }
346
+ .jasmine-performance-view table {
347
+ border-spacing: 5px;
348
+ }
349
+ .jasmine-performance-view th, .jasmine-performance-view td {
350
+ text-align: left;
326
351
  }
@@ -50,11 +50,12 @@ var getJasmineRequireObj = (function() {
50
50
  j$.private.util = jRequire.util(j$);
51
51
  j$.private.errors = jRequire.errors();
52
52
  j$.private.formatErrorMsg = jRequire.formatErrorMsg(j$);
53
+ j$.private.AllOf = jRequire.AllOf(j$);
53
54
  j$.private.Any = jRequire.Any(j$);
54
55
  j$.private.Anything = jRequire.Anything(j$);
55
56
  j$.private.CallTracker = jRequire.CallTracker(j$);
56
57
  j$.private.MockDate = jRequire.MockDate(j$);
57
- j$.private.getClearStack = jRequire.clearStack(j$);
58
+ j$.private.getStackClearer = jRequire.StackClearer(j$);
58
59
  j$.private.Clock = jRequire.Clock();
59
60
  j$.private.DelayedFunctionScheduler = jRequire.DelayedFunctionScheduler(j$);
60
61
  j$.private.Deprecator = jRequire.Deprecator(j$);
@@ -407,6 +408,19 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
407
408
  );
408
409
  };
409
410
 
411
+ /**
412
+ * Get an {@link AsymmetricEqualityTester} that will succeed if the actual
413
+ * value being compared matches every provided equality tester.
414
+ * @name asymmetricEqualityTesters.allOf
415
+ * @emittedName jasmine.allOf
416
+ * @since 5.13.0
417
+ * @function
418
+ * @param {...*} arguments - The asymmetric equality checkers to compare.
419
+ */
420
+ j$.allOf = function() {
421
+ return new j$.AllOf(...arguments);
422
+ };
423
+
410
424
  /**
411
425
  * Get an {@link AsymmetricEqualityTester} that will succeed if the actual
412
426
  * value being compared is an instance of the specified class/constructor.
@@ -849,8 +863,11 @@ getJasmineRequireObj().Spec = function(j$) {
849
863
  // Key and value will eventually be cloned during reporting. The error
850
864
  // thrown at that point if they aren't cloneable isn't very helpful.
851
865
  // Throw a better one now.
852
- j$.private.util.assertReporterCloneable(key, 'Key');
866
+ if (!j$.private.isString(key)) {
867
+ throw new Error('Key must be a string');
868
+ }
853
869
  j$.private.util.assertReporterCloneable(value, 'Value');
870
+
854
871
  this.#executionState.properties = this.#executionState.properties || {};
855
872
  this.#executionState.properties[key] = value;
856
873
  }
@@ -930,12 +947,11 @@ getJasmineRequireObj().Spec = function(j$) {
930
947
  * @property {String} description - The description passed to the {@link it} that created this spec.
931
948
  * @property {String} fullName - The full description including all ancestors of this spec.
932
949
  * @property {String|null} parentSuiteId - The ID of the suite containing this spec, or null if this spec is not in a describe().
933
- * @property {String} filename - Deprecated. The name of the file the spec was defined in.
950
+ * @property {String} filename - The name of the file the spec was defined in.
934
951
  * Note: The value may be incorrect if zone.js is installed or
935
952
  * `it`/`fit`/`xit` have been replaced with versions that don't maintain the
936
- * same call stack height as the originals. This property may be removed in
937
- * a future version unless there is enough user interest in keeping it.
938
- * See {@link https://github.com/jasmine/jasmine/issues/2065}.
953
+ * same call stack height as the originals. You can fix that by setting
954
+ * {@link Configuration#extraItStackFrames}.
939
955
  * @property {ExpectationResult[]} failedExpectations - The list of expectations that failed during execution of this spec.
940
956
  * @property {ExpectationResult[]} passedExpectations - The list of expectations that passed during execution of this spec.
941
957
  * @property {ExpectationResult[]} deprecationWarnings - The list of deprecation warnings that occurred during execution this spec.
@@ -1117,7 +1133,20 @@ getJasmineRequireObj().Spec = function(j$) {
1117
1133
  * @returns {Array.<string>}
1118
1134
  * @since 5.7.0
1119
1135
  */
1120
- getPath: this.getPath.bind(this)
1136
+ getPath: this.getPath.bind(this),
1137
+
1138
+ /**
1139
+ * The name of the file the spec was defined in.
1140
+ * Note: The value may be incorrect if zone.js is installed or
1141
+ * `it`/`fit`/`xit` have been replaced with versions that don't maintain the
1142
+ * same call stack height as the originals. You can fix that by setting
1143
+ * {@link Configuration#extraItStackFrames}.
1144
+ * @name Spec#filename
1145
+ * @readonly
1146
+ * @type {string}
1147
+ * @since 5.13.0
1148
+ */
1149
+ filename: this.filename
1121
1150
  };
1122
1151
  }
1123
1152
 
@@ -1196,6 +1225,8 @@ getJasmineRequireObj().Order = function() {
1196
1225
  getJasmineRequireObj().Env = function(j$) {
1197
1226
  'use strict';
1198
1227
 
1228
+ const DEFAULT_IT_DESCRIBE_STACK_DEPTH = 3;
1229
+
1199
1230
  /**
1200
1231
  * @class Env
1201
1232
  * @since 2.0.0
@@ -1213,7 +1244,7 @@ getJasmineRequireObj().Env = function(j$) {
1213
1244
 
1214
1245
  const realSetTimeout = global.setTimeout;
1215
1246
  const realClearTimeout = global.clearTimeout;
1216
- const clearStack = j$.private.getClearStack(global);
1247
+ const stackClearer = j$.private.getStackClearer(global);
1217
1248
  this.clock = new j$.private.Clock(
1218
1249
  global,
1219
1250
  function() {
@@ -1223,7 +1254,7 @@ getJasmineRequireObj().Env = function(j$) {
1223
1254
  );
1224
1255
 
1225
1256
  const globalErrors = new GlobalErrors(
1226
- undefined,
1257
+ global,
1227
1258
  // Configuration is late-bound because GlobalErrors needs to be constructed
1228
1259
  // before it's set to detect load-time errors in browsers
1229
1260
  () => this.configuration()
@@ -1292,6 +1323,7 @@ getJasmineRequireObj().Env = function(j$) {
1292
1323
 
1293
1324
  config.update(changes);
1294
1325
  deprecator.verboseDeprecations(config.verboseDeprecations);
1326
+ stackClearer.setSafariYieldStrategy(config.safariYieldStrategy);
1295
1327
  };
1296
1328
 
1297
1329
  /**
@@ -1494,7 +1526,7 @@ getJasmineRequireObj().Env = function(j$) {
1494
1526
  };
1495
1527
 
1496
1528
  function runQueue(options) {
1497
- options.clearStack = options.clearStack || clearStack;
1529
+ options.clearStack = options.clearStack || stackClearer;
1498
1530
  options.timeout = {
1499
1531
  setTimeout: realSetTimeout,
1500
1532
  clearTimeout: realClearTimeout
@@ -1786,14 +1818,14 @@ getJasmineRequireObj().Env = function(j$) {
1786
1818
 
1787
1819
  this.describe = function(description, definitionFn) {
1788
1820
  ensureIsNotNested('describe');
1789
- const filename = callerCallerFilename();
1821
+ const filename = indirectCallerFilename(describeStackDepth());
1790
1822
  return suiteBuilder.describe(description, definitionFn, filename)
1791
1823
  .metadata;
1792
1824
  };
1793
1825
 
1794
1826
  this.xdescribe = function(description, definitionFn) {
1795
1827
  ensureIsNotNested('xdescribe');
1796
- const filename = callerCallerFilename();
1828
+ const filename = indirectCallerFilename(describeStackDepth());
1797
1829
  return suiteBuilder.xdescribe(description, definitionFn, filename)
1798
1830
  .metadata;
1799
1831
  };
@@ -1801,30 +1833,38 @@ getJasmineRequireObj().Env = function(j$) {
1801
1833
  this.fdescribe = function(description, definitionFn) {
1802
1834
  ensureIsNotNested('fdescribe');
1803
1835
  ensureNonParallel('fdescribe');
1804
- const filename = callerCallerFilename();
1836
+ const filename = indirectCallerFilename(describeStackDepth());
1805
1837
  return suiteBuilder.fdescribe(description, definitionFn, filename)
1806
1838
  .metadata;
1807
1839
  };
1808
1840
 
1809
1841
  this.it = function(description, fn, timeout) {
1810
1842
  ensureIsNotNested('it');
1811
- const filename = callerCallerFilename();
1843
+ const filename = indirectCallerFilename(itStackDepth());
1812
1844
  return suiteBuilder.it(description, fn, timeout, filename).metadata;
1813
1845
  };
1814
1846
 
1815
1847
  this.xit = function(description, fn, timeout) {
1816
1848
  ensureIsNotNested('xit');
1817
- const filename = callerCallerFilename();
1849
+ const filename = indirectCallerFilename(itStackDepth());
1818
1850
  return suiteBuilder.xit(description, fn, timeout, filename).metadata;
1819
1851
  };
1820
1852
 
1821
1853
  this.fit = function(description, fn, timeout) {
1822
1854
  ensureIsNotNested('fit');
1823
1855
  ensureNonParallel('fit');
1824
- const filename = callerCallerFilename();
1856
+ const filename = indirectCallerFilename(itStackDepth());
1825
1857
  return suiteBuilder.fit(description, fn, timeout, filename).metadata;
1826
1858
  };
1827
1859
 
1860
+ function itStackDepth() {
1861
+ return DEFAULT_IT_DESCRIBE_STACK_DEPTH + config.extraItStackFrames;
1862
+ }
1863
+
1864
+ function describeStackDepth() {
1865
+ return DEFAULT_IT_DESCRIBE_STACK_DEPTH + config.extraDescribeStackFrames;
1866
+ }
1867
+
1828
1868
  /**
1829
1869
  * Get a user-defined property as part of the properties field of {@link SpecDoneEvent}
1830
1870
  * @name Env#getSpecProperty
@@ -2010,11 +2050,12 @@ getJasmineRequireObj().Env = function(j$) {
2010
2050
  };
2011
2051
  }
2012
2052
 
2013
- function callerCallerFilename() {
2053
+ function indirectCallerFilename(depth) {
2014
2054
  const frames = new j$.private.StackTrace(new Error()).frames;
2015
- // frames[3] should always exist except in Jasmine's own tests, which bypass
2016
- // the global it/describe layer, but don't crash if it doesn't.
2017
- return frames[3] && frames[3].file;
2055
+ // The specified frame should always exist except in Jasmine's own tests,
2056
+ // which bypass the global it/describe layer, but could be absent in case
2057
+ // of misconfiguration. Don't crash if it's absent.
2058
+ return frames[depth] && frames[depth].file;
2018
2059
  }
2019
2060
 
2020
2061
  return Env;
@@ -2152,6 +2193,36 @@ getJasmineRequireObj().JsApiReporter = function(j$) {
2152
2193
  return JsApiReporter;
2153
2194
  };
2154
2195
 
2196
+ getJasmineRequireObj().AllOf = function(j$) {
2197
+ 'use strict';
2198
+
2199
+ function AllOf() {
2200
+ const expectedValues = Array.from(arguments);
2201
+ if (expectedValues.length === 0) {
2202
+ throw new TypeError(
2203
+ 'jasmine.allOf() expects at least one argument to be passed.'
2204
+ );
2205
+ }
2206
+ this.expectedValues = expectedValues;
2207
+ }
2208
+
2209
+ AllOf.prototype.asymmetricMatch = function(other, matchersUtil) {
2210
+ for (const expectedValue of this.expectedValues) {
2211
+ if (!matchersUtil.equals(other, expectedValue)) {
2212
+ return false;
2213
+ }
2214
+ }
2215
+
2216
+ return true;
2217
+ };
2218
+
2219
+ AllOf.prototype.jasmineToString = function(pp) {
2220
+ return '<jasmine.allOf(' + pp(this.expectedValues) + ')>';
2221
+ };
2222
+
2223
+ return AllOf;
2224
+ };
2225
+
2155
2226
  getJasmineRequireObj().Any = function(j$) {
2156
2227
  'use strict';
2157
2228
 
@@ -2849,131 +2920,6 @@ getJasmineRequireObj().CallTracker = function(j$) {
2849
2920
  return CallTracker;
2850
2921
  };
2851
2922
 
2852
- getJasmineRequireObj().clearStack = function(j$) {
2853
- 'use strict';
2854
-
2855
- const maxInlineCallCount = 10;
2856
-
2857
- function browserQueueMicrotaskImpl(global) {
2858
- const unclampedSetTimeout = getUnclampedSetTimeout(global);
2859
- const { queueMicrotask } = global;
2860
- let currentCallCount = 0;
2861
- return function clearStack(fn) {
2862
- currentCallCount++;
2863
-
2864
- if (currentCallCount < maxInlineCallCount) {
2865
- queueMicrotask(fn);
2866
- } else {
2867
- currentCallCount = 0;
2868
- unclampedSetTimeout(fn);
2869
- }
2870
- };
2871
- }
2872
-
2873
- function nodeQueueMicrotaskImpl(global) {
2874
- const { queueMicrotask } = global;
2875
-
2876
- return function(fn) {
2877
- queueMicrotask(fn);
2878
- };
2879
- }
2880
-
2881
- function messageChannelImpl(global) {
2882
- const { setTimeout } = global;
2883
- const postMessage = getPostMessage(global);
2884
-
2885
- let currentCallCount = 0;
2886
- return function clearStack(fn) {
2887
- currentCallCount++;
2888
-
2889
- if (currentCallCount < maxInlineCallCount) {
2890
- postMessage(fn);
2891
- } else {
2892
- currentCallCount = 0;
2893
- setTimeout(fn);
2894
- }
2895
- };
2896
- }
2897
-
2898
- function getUnclampedSetTimeout(global) {
2899
- const { setTimeout } = global;
2900
- if (!global.MessageChannel) {
2901
- return setTimeout;
2902
- }
2903
-
2904
- const postMessage = getPostMessage(global);
2905
- return function unclampedSetTimeout(fn) {
2906
- postMessage(function() {
2907
- setTimeout(fn);
2908
- });
2909
- };
2910
- }
2911
-
2912
- function getPostMessage(global) {
2913
- const { MessageChannel, setTimeout } = global;
2914
- const channel = new MessageChannel();
2915
- let head = {};
2916
- let tail = head;
2917
-
2918
- let taskRunning = false;
2919
- channel.port1.onmessage = function() {
2920
- head = head.next;
2921
- const task = head.task;
2922
- delete head.task;
2923
-
2924
- if (taskRunning) {
2925
- setTimeout(task, 0);
2926
- } else {
2927
- try {
2928
- taskRunning = true;
2929
- task();
2930
- } finally {
2931
- taskRunning = false;
2932
- }
2933
- }
2934
- };
2935
-
2936
- return function postMessage(fn) {
2937
- tail = tail.next = { task: fn };
2938
- channel.port2.postMessage(0);
2939
- };
2940
- }
2941
-
2942
- function getClearStack(global) {
2943
- const NODE_JS =
2944
- global.process &&
2945
- global.process.versions &&
2946
- typeof global.process.versions.node === 'string';
2947
-
2948
- // Windows builds of WebKit have a fairly generic user agent string when no application name is provided:
2949
- // e.g. "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/605.1.15 (KHTML, like Gecko)"
2950
- const SAFARI_OR_WIN_WEBKIT =
2951
- global.navigator &&
2952
- /(^((?!chrome|android).)*safari)|(Win64; x64\) AppleWebKit\/[0-9.]+ \(KHTML, like Gecko\)$)/i.test(
2953
- global.navigator.userAgent
2954
- );
2955
-
2956
- if (NODE_JS) {
2957
- // Unlike browsers, Node doesn't require us to do a periodic setTimeout
2958
- // so we avoid the overhead.
2959
- return nodeQueueMicrotaskImpl(global);
2960
- } else if (SAFARI_OR_WIN_WEBKIT || !global.MessageChannel /* tests */) {
2961
- // queueMicrotask is dramatically faster than MessageChannel in Safari
2962
- // and other WebKit-based browsers, such as the one distributed by Playwright
2963
- // to test Safari-like behavior on Windows.
2964
- // Some of our own integration tests provide a mock queueMicrotask in all
2965
- // environments because it's simpler to mock than MessageChannel.
2966
- return browserQueueMicrotaskImpl(global);
2967
- } else {
2968
- // MessageChannel is faster than queueMicrotask in supported browsers
2969
- // other than Safari.
2970
- return messageChannelImpl(global);
2971
- }
2972
- }
2973
-
2974
- return getClearStack;
2975
- };
2976
-
2977
2923
  getJasmineRequireObj().Clock = function() {
2978
2924
  'use strict';
2979
2925
 
@@ -3507,7 +3453,45 @@ getJasmineRequireObj().Configuration = function(j$) {
3507
3453
  * @type Boolean
3508
3454
  * @default false
3509
3455
  */
3510
- detectLateRejectionHandling: false
3456
+ detectLateRejectionHandling: false,
3457
+
3458
+ /**
3459
+ * The number of extra stack frames inserted by a wrapper around {@link it}
3460
+ * or by some other local modification. Jasmine uses this to determine the
3461
+ * filename for {@link SpecStartedEvent} and {@link SpecDoneEvent}.
3462
+ * @name Configuration#extraItStackFrames
3463
+ * @since 5.13.0
3464
+ * @type number
3465
+ * @default 0
3466
+ */
3467
+ extraItStackFrames: 0,
3468
+
3469
+ /**
3470
+ * The number of extra stack frames inserted by a wrapper around
3471
+ * {@link describe} or by some other local modification. Jasmine uses this
3472
+ * to determine the filename for {@link SpecStartedEvent} and
3473
+ * {@link SpecDoneEvent}.
3474
+ * @name Configuration#extraDescribeStackFrames
3475
+ * @since 5.13.0
3476
+ * @type number
3477
+ * @default 0
3478
+ */
3479
+ extraDescribeStackFrames: 0,
3480
+
3481
+ /**
3482
+ * The strategy to use in Safari and similar browsers to determine how often
3483
+ * to yield control by calling setTimeout. If set to "count", the default,
3484
+ * the frequency of setTimeout calls is based on the number of relevant
3485
+ * function calls. If set to "time", the frequency of setTimeout calls is
3486
+ * based on elapsed time. Using "time" may provide a significant performance
3487
+ * improvement, but as of 6.0 it hasn't been tested with a wide variety of
3488
+ * workloads and should be considered experimental.
3489
+ * @name Configuration#safariYieldStrategy
3490
+ * @since 6.0.0
3491
+ * @type 'count' | 'time'
3492
+ * @default 'count'
3493
+ */
3494
+ safariYieldStrategy: 'count'
3511
3495
  };
3512
3496
  Object.freeze(defaultConfig);
3513
3497
 
@@ -3558,6 +3542,28 @@ getJasmineRequireObj().Configuration = function(j$) {
3558
3542
  if (typeof changes.seed !== 'undefined') {
3559
3543
  this.#values.seed = changes.seed;
3560
3544
  }
3545
+
3546
+ // 0 is a valid value for both of these, so a truthiness check wouldn't work
3547
+ if (typeof changes.extraItStackFrames !== 'undefined') {
3548
+ this.#values.extraItStackFrames = changes.extraItStackFrames;
3549
+ }
3550
+
3551
+ if (typeof changes.extraDescribeStackFrames !== 'undefined') {
3552
+ this.#values.extraDescribeStackFrames =
3553
+ changes.extraDescribeStackFrames;
3554
+ }
3555
+
3556
+ if (typeof changes.safariYieldStrategy !== 'undefined') {
3557
+ const v = changes.safariYieldStrategy;
3558
+
3559
+ if (v === 'count' || v === 'time') {
3560
+ this.#values.safariYieldStrategy = v;
3561
+ } else {
3562
+ throw new Error(
3563
+ "Invalid safariYieldStrategy value. Valid values are 'count' and 'time'."
3564
+ );
3565
+ }
3566
+ }
3561
3567
  }
3562
3568
  }
3563
3569
 
@@ -8560,11 +8566,11 @@ getJasmineRequireObj().QueueRunner = function(j$) {
8560
8566
  }
8561
8567
 
8562
8568
  this.onComplete = attrs.onComplete || emptyFn;
8563
- this.clearStack =
8564
- attrs.clearStack ||
8565
- function(fn) {
8569
+ this.clearStack = attrs.clearStack || {
8570
+ clearStack(fn) {
8566
8571
  fn();
8567
- };
8572
+ }
8573
+ };
8568
8574
  this.onException = attrs.onException || emptyFn;
8569
8575
  this.onMultipleDone = attrs.onMultipleDone || fallbackOnMultipleDone;
8570
8576
  this.userContext = attrs.userContext || new j$.private.UserContext();
@@ -8744,7 +8750,7 @@ getJasmineRequireObj().QueueRunner = function(j$) {
8744
8750
  }
8745
8751
  }
8746
8752
 
8747
- this.clearStack(() => {
8753
+ this.clearStack.clearStack(() => {
8748
8754
  this.globalErrors.popListener(this.handleFinalError);
8749
8755
 
8750
8756
  if (this.errored_) {
@@ -8902,6 +8908,7 @@ getJasmineRequireObj().reporterEvents = function(j$) {
8902
8908
  * {@link ReporterCapabilities} will apply.
8903
8909
  * @name Reporter#reporterCapabilities
8904
8910
  * @type ReporterCapabilities | undefined
8911
+ * @optional
8905
8912
  * @since 5.0
8906
8913
  */
8907
8914
  /**
@@ -8968,6 +8975,7 @@ getJasmineRequireObj().reporterEvents = function(j$) {
8968
8975
  /**
8969
8976
  * `specStarted` is invoked when an `it` starts to run (including associated `beforeEach` functions)
8970
8977
  * @function
8978
+ * @optional
8971
8979
  * @name Reporter#specStarted
8972
8980
  * @param {SpecStartedEvent} result Information about the individual {@link it} being run
8973
8981
  * @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.
@@ -10678,6 +10686,164 @@ getJasmineRequireObj().SpyStrategy = function(j$) {
10678
10686
  return SpyStrategy;
10679
10687
  };
10680
10688
 
10689
+ getJasmineRequireObj().StackClearer = function(j$) {
10690
+ 'use strict';
10691
+
10692
+ const maxInlineCallCount = 10;
10693
+ // 25ms gives a good balance of speed and UI responsiveness when running
10694
+ // jasmine-core's own tests in Safari 18. The exact value isn't critical.
10695
+ const safariYieldIntervalMs = 25;
10696
+
10697
+ function browserQueueMicrotaskImpl(global) {
10698
+ const unclampedSetTimeout = getUnclampedSetTimeout(global);
10699
+ const { queueMicrotask } = global;
10700
+ let yieldStrategy = 'count';
10701
+ let currentCallCount = 0; // for count strategy
10702
+ let nextSetTimeoutTime; // for time strategy
10703
+
10704
+ return {
10705
+ clearStack(fn) {
10706
+ currentCallCount++;
10707
+ let shouldSetTimeout;
10708
+
10709
+ if (yieldStrategy === 'time') {
10710
+ const now = new Date().getTime();
10711
+ shouldSetTimeout = now >= nextSetTimeoutTime;
10712
+ if (shouldSetTimeout) {
10713
+ nextSetTimeoutTime = now + safariYieldIntervalMs;
10714
+ }
10715
+ } else {
10716
+ shouldSetTimeout = currentCallCount >= maxInlineCallCount;
10717
+ if (shouldSetTimeout) {
10718
+ currentCallCount = 0;
10719
+ }
10720
+ }
10721
+
10722
+ if (shouldSetTimeout) {
10723
+ unclampedSetTimeout(fn);
10724
+ } else {
10725
+ queueMicrotask(fn);
10726
+ }
10727
+ },
10728
+ setSafariYieldStrategy(strategy) {
10729
+ yieldStrategy = strategy;
10730
+
10731
+ if (yieldStrategy === 'time') {
10732
+ nextSetTimeoutTime = new Date().getTime() + safariYieldIntervalMs;
10733
+ }
10734
+ }
10735
+ };
10736
+ }
10737
+
10738
+ function nodeQueueMicrotaskImpl(global) {
10739
+ const { queueMicrotask } = global;
10740
+
10741
+ return {
10742
+ clearStack(fn) {
10743
+ queueMicrotask(fn);
10744
+ },
10745
+ setSafariYieldStrategy() {}
10746
+ };
10747
+ }
10748
+
10749
+ function messageChannelImpl(global) {
10750
+ const { setTimeout } = global;
10751
+ const postMessage = getPostMessage(global);
10752
+
10753
+ let currentCallCount = 0;
10754
+
10755
+ return {
10756
+ clearStack(fn) {
10757
+ currentCallCount++;
10758
+
10759
+ if (currentCallCount < maxInlineCallCount) {
10760
+ postMessage(fn);
10761
+ } else {
10762
+ currentCallCount = 0;
10763
+ setTimeout(fn);
10764
+ }
10765
+ },
10766
+ setSafariYieldStrategy() {}
10767
+ };
10768
+ }
10769
+
10770
+ function getUnclampedSetTimeout(global) {
10771
+ const { setTimeout } = global;
10772
+ if (!global.MessageChannel) {
10773
+ return setTimeout;
10774
+ }
10775
+
10776
+ const postMessage = getPostMessage(global);
10777
+ return function unclampedSetTimeout(fn) {
10778
+ postMessage(function() {
10779
+ setTimeout(fn);
10780
+ });
10781
+ };
10782
+ }
10783
+
10784
+ function getPostMessage(global) {
10785
+ const { MessageChannel, setTimeout } = global;
10786
+ const channel = new MessageChannel();
10787
+ let head = {};
10788
+ let tail = head;
10789
+
10790
+ let taskRunning = false;
10791
+ channel.port1.onmessage = function() {
10792
+ head = head.next;
10793
+ const task = head.task;
10794
+ delete head.task;
10795
+
10796
+ if (taskRunning) {
10797
+ setTimeout(task, 0);
10798
+ } else {
10799
+ try {
10800
+ taskRunning = true;
10801
+ task();
10802
+ } finally {
10803
+ taskRunning = false;
10804
+ }
10805
+ }
10806
+ };
10807
+
10808
+ return function postMessage(fn) {
10809
+ tail = tail.next = { task: fn };
10810
+ channel.port2.postMessage(0);
10811
+ };
10812
+ }
10813
+
10814
+ function getStackClearer(global) {
10815
+ const NODE_JS =
10816
+ global.process &&
10817
+ global.process.versions &&
10818
+ typeof global.process.versions.node === 'string';
10819
+
10820
+ // Windows builds of WebKit have a fairly generic user agent string when no application name is provided:
10821
+ // e.g. "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/605.1.15 (KHTML, like Gecko)"
10822
+ const SAFARI_OR_WIN_WEBKIT =
10823
+ global.navigator &&
10824
+ /(^((?!chrome|android).)*safari)|(Win64; x64\) AppleWebKit\/[0-9.]+ \(KHTML, like Gecko\)$)/i.test(
10825
+ global.navigator.userAgent
10826
+ );
10827
+
10828
+ if (NODE_JS) {
10829
+ // Unlike browsers, Node doesn't require us to do a periodic setTimeout
10830
+ // so we avoid the overhead.
10831
+ return nodeQueueMicrotaskImpl(global);
10832
+ } else if (SAFARI_OR_WIN_WEBKIT) {
10833
+ // queueMicrotask is dramatically faster than MessageChannel in Safari
10834
+ // and other WebKit-based browsers, such as the one distributed by Playwright
10835
+ // to test Safari-like behavior on Windows.
10836
+ return browserQueueMicrotaskImpl(global);
10837
+ } else {
10838
+ // MessageChannel is faster than queueMicrotask in supported browsers
10839
+ // other than Safari.
10840
+ return messageChannelImpl(global);
10841
+ }
10842
+ }
10843
+
10844
+ return getStackClearer;
10845
+ };
10846
+
10681
10847
  getJasmineRequireObj().StackTrace = function(j$) {
10682
10848
  'use strict';
10683
10849
 
@@ -10851,8 +11017,11 @@ getJasmineRequireObj().Suite = function(j$) {
10851
11017
  // Key and value will eventually be cloned during reporting. The error
10852
11018
  // thrown at that point if they aren't cloneable isn't very helpful.
10853
11019
  // Throw a better one now.
10854
- j$.private.util.assertReporterCloneable(key, 'Key');
11020
+ if (!j$.private.isString(key)) {
11021
+ throw new Error('Key must be a string');
11022
+ }
10855
11023
  j$.private.util.assertReporterCloneable(value, 'Value');
11024
+
10856
11025
  this.#result.properties = this.#result.properties || {};
10857
11026
  this.#result.properties[key] = value;
10858
11027
  }
@@ -10960,12 +11129,11 @@ getJasmineRequireObj().Suite = function(j$) {
10960
11129
  * @property {String} description - The description text passed to the {@link describe} that made this suite.
10961
11130
  * @property {String} fullName - The full description including all ancestors of this suite.
10962
11131
  * @property {String|null} parentSuiteId - The ID of the suite containing this suite, or null if this is not in another describe().
10963
- * @property {String} filename - Deprecated. The name of the file the suite was defined in.
11132
+ * @property {String} filename - The name of the file the suite was defined in.
10964
11133
  * Note: The value may be incorrect if zone.js is installed or
10965
11134
  * `describe`/`fdescribe`/`xdescribe` have been replaced with versions that
10966
- * don't maintain the same call stack height as the originals. This property
10967
- * may be removed in a future version unless there is enough user interest
10968
- * in keeping it. See {@link https://github.com/jasmine/jasmine/issues/2065}.
11135
+ * don't maintain the same call stack height as the originals. You can fix
11136
+ * that by setting {@link Configuration#extraDescribeStackFrames}.
10969
11137
  * @property {ExpectationResult[]} failedExpectations - The list of expectations that failed in an {@link afterAll} for this suite.
10970
11138
  * @property {ExpectationResult[]} deprecationWarnings - The list of deprecation warnings that occurred on this suite.
10971
11139
  * @property {String} status - Once the suite has completed, this string represents the pass/fail status of this suite.
@@ -11173,6 +11341,19 @@ getJasmineRequireObj().Suite = function(j$) {
11173
11341
  * @since 2.0.0
11174
11342
  */
11175
11343
  this.description = suite.description;
11344
+
11345
+ /**
11346
+ * The name of the file the suite was defined in.
11347
+ * Note: The value may be incorrect if zone.js is installed or
11348
+ * `describe`/`fdescribe`/`xdescribe` have been replaced with versions
11349
+ * that don't maintain the same call stack height as the originals. You
11350
+ * can fix that by setting {@link Configuration#extraItStackFrames}.
11351
+ * @name Suite#filename
11352
+ * @readonly
11353
+ * @type {string}
11354
+ * @since 5.13.0
11355
+ */
11356
+ this.filename = suite.filename;
11176
11357
  }
11177
11358
 
11178
11359
  /**
@@ -11852,7 +12033,10 @@ getJasmineRequireObj().TreeRunner = function(j$) {
11852
12033
  _executeSpec(spec, specOverallDone) {
11853
12034
  const onStart = next => {
11854
12035
  this.#currentRunableTracker.setCurrentSpec(spec);
11855
- this.#runableResources.initForRunable(spec.id, spec.parentSuiteId);
12036
+ this.#runableResources.initForRunable(
12037
+ spec.id,
12038
+ spec.parentSuiteId || this.#executionTree.topSuite.id
12039
+ );
11856
12040
  this.#reportDispatcher.specStarted(spec.startedEvent()).then(next);
11857
12041
  };
11858
12042
  const resultCallback = (result, next) => {
@@ -12111,5 +12295,5 @@ getJasmineRequireObj().UserContext = function(j$) {
12111
12295
  };
12112
12296
 
12113
12297
  getJasmineRequireObj().version = function() {
12114
- return '6.0.0-alpha.1';
12298
+ return '6.0.0-alpha.2';
12115
12299
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "jasmine-core",
3
3
  "license": "MIT",
4
- "version": "6.0.0-alpha.1",
4
+ "version": "6.0.0-alpha.2",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "https://github.com/jasmine/jasmine.git"