@rstest/core 0.3.1 → 0.3.3

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/LICENSE.md CHANGED
@@ -928,6 +928,20 @@ Licensed under MIT license in the repository at git+https://github.com/errwischt
928
928
  > OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
929
929
  > SOFTWARE.
930
930
 
931
+ ### strip-ansi
932
+
933
+ Licensed under MIT license.
934
+
935
+ > MIT License
936
+ >
937
+ > Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)
938
+ >
939
+ > Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
940
+ >
941
+ > The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
942
+ >
943
+ > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
944
+
931
945
  ### supports-color
932
946
 
933
947
  Licensed under MIT license.
@@ -1,165 +1,17 @@
1
1
  import 'module';
2
2
  /*#__PURE__*/ import.meta.url;
3
- export const __webpack_id__ = "12";
3
+ export const __webpack_id__ = "263";
4
4
  export const __webpack_ids__ = [
5
- "12"
5
+ "263"
6
6
  ];
7
7
  export const __webpack_modules__ = {
8
- "../../node_modules/.pnpm/stacktrace-parser@0.1.11/node_modules/stacktrace-parser/dist/stack-trace-parser.esm.js": function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
9
- __webpack_require__.d(__webpack_exports__, {
10
- q: ()=>parse
11
- });
12
- var UNKNOWN_FUNCTION = '<unknown>';
13
- function parse(stackString) {
14
- var lines = stackString.split('\n');
15
- return lines.reduce(function(stack, line) {
16
- var parseResult = parseChrome(line) || parseWinjs(line) || parseGecko(line) || parseNode(line) || parseJSC(line);
17
- if (parseResult) stack.push(parseResult);
18
- return stack;
19
- }, []);
20
- }
21
- var chromeRe = /^\s*at (.*?) ?\(((?:file|https?|blob|chrome-extension|native|eval|webpack|rsc|<anonymous>|\/|[a-z]:\\|\\\\).*?)(?::(\d+))?(?::(\d+))?\)?\s*$/i;
22
- var chromeEvalRe = /\((\S*)(?::(\d+))(?::(\d+))\)/;
23
- function parseChrome(line) {
24
- var parts = chromeRe.exec(line);
25
- if (!parts) return null;
26
- var isNative = parts[2] && 0 === parts[2].indexOf('native');
27
- var isEval = parts[2] && 0 === parts[2].indexOf('eval');
28
- var submatch = chromeEvalRe.exec(parts[2]);
29
- if (isEval && null != submatch) {
30
- parts[2] = submatch[1];
31
- parts[3] = submatch[2];
32
- parts[4] = submatch[3];
33
- }
34
- return {
35
- file: isNative ? null : parts[2],
36
- methodName: parts[1] || UNKNOWN_FUNCTION,
37
- arguments: isNative ? [
38
- parts[2]
39
- ] : [],
40
- lineNumber: parts[3] ? +parts[3] : null,
41
- column: parts[4] ? +parts[4] : null
42
- };
43
- }
44
- var winjsRe = /^\s*at (?:((?:\[object object\])?.+) )?\(?((?:file|ms-appx|https?|webpack|rsc|blob):.*?):(\d+)(?::(\d+))?\)?\s*$/i;
45
- function parseWinjs(line) {
46
- var parts = winjsRe.exec(line);
47
- if (!parts) return null;
48
- return {
49
- file: parts[2],
50
- methodName: parts[1] || UNKNOWN_FUNCTION,
51
- arguments: [],
52
- lineNumber: +parts[3],
53
- column: parts[4] ? +parts[4] : null
54
- };
55
- }
56
- var geckoRe = /^\s*(.*?)(?:\((.*?)\))?(?:^|@)((?:file|https?|blob|chrome|webpack|rsc|resource|\[native).*?|[^@]*bundle)(?::(\d+))?(?::(\d+))?\s*$/i;
57
- var geckoEvalRe = /(\S+) line (\d+)(?: > eval line \d+)* > eval/i;
58
- function parseGecko(line) {
59
- var parts = geckoRe.exec(line);
60
- if (!parts) return null;
61
- var isEval = parts[3] && parts[3].indexOf(' > eval') > -1;
62
- var submatch = geckoEvalRe.exec(parts[3]);
63
- if (isEval && null != submatch) {
64
- parts[3] = submatch[1];
65
- parts[4] = submatch[2];
66
- parts[5] = null;
67
- }
68
- return {
69
- file: parts[3],
70
- methodName: parts[1] || UNKNOWN_FUNCTION,
71
- arguments: parts[2] ? parts[2].split(',') : [],
72
- lineNumber: parts[4] ? +parts[4] : null,
73
- column: parts[5] ? +parts[5] : null
74
- };
75
- }
76
- var javaScriptCoreRe = /^\s*(?:([^@]*)(?:\((.*?)\))?@)?(\S.*?):(\d+)(?::(\d+))?\s*$/i;
77
- function parseJSC(line) {
78
- var parts = javaScriptCoreRe.exec(line);
79
- if (!parts) return null;
80
- return {
81
- file: parts[3],
82
- methodName: parts[1] || UNKNOWN_FUNCTION,
83
- arguments: [],
84
- lineNumber: +parts[4],
85
- column: parts[5] ? +parts[5] : null
86
- };
87
- }
88
- var nodeRe = /^\s*at (?:((?:\[object object\])?[^\\/]+(?: \[as \S+\])?) )?\(?(.*?):(\d+)(?::(\d+))?\)?\s*$/i;
89
- function parseNode(line) {
90
- var parts = nodeRe.exec(line);
91
- if (!parts) return null;
92
- return {
93
- file: parts[2],
94
- methodName: parts[1] || UNKNOWN_FUNCTION,
95
- arguments: [],
96
- lineNumber: +parts[3],
97
- column: parts[4] ? +parts[4] : null
98
- };
99
- }
100
- },
101
8
  "./src/core/index.ts": function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
102
9
  __webpack_require__.d(__webpack_exports__, {
103
10
  createRstest: ()=>createRstest
104
11
  });
12
+ var external_node_fs_ = __webpack_require__("node:fs");
13
+ var manager = __webpack_require__("../../node_modules/.pnpm/@vitest+snapshot@3.2.4/node_modules/@vitest/snapshot/dist/manager.js");
105
14
  var external_pathe_ = __webpack_require__("pathe");
106
- class SnapshotManager {
107
- summary;
108
- extension = ".snap";
109
- constructor(options){
110
- this.options = options;
111
- this.clear();
112
- }
113
- clear() {
114
- this.summary = emptySummary(this.options);
115
- }
116
- add(result) {
117
- addSnapshotResult(this.summary, result);
118
- }
119
- resolvePath(testPath, context) {
120
- const resolver = this.options.resolveSnapshotPath || (()=>(0, external_pathe_.join)((0, external_pathe_.join)((0, external_pathe_.dirname)(testPath), "__snapshots__"), `${(0, external_pathe_.basename)(testPath)}${this.extension}`));
121
- const path = resolver(testPath, this.extension, context);
122
- return path;
123
- }
124
- resolveRawPath(testPath, rawPath) {
125
- return (0, external_pathe_.isAbsolute)(rawPath) ? rawPath : (0, external_pathe_.resolve)((0, external_pathe_.dirname)(testPath), rawPath);
126
- }
127
- }
128
- function emptySummary(options) {
129
- const summary = {
130
- added: 0,
131
- failure: false,
132
- filesAdded: 0,
133
- filesRemoved: 0,
134
- filesRemovedList: [],
135
- filesUnmatched: 0,
136
- filesUpdated: 0,
137
- matched: 0,
138
- total: 0,
139
- unchecked: 0,
140
- uncheckedKeysByFile: [],
141
- unmatched: 0,
142
- updated: 0,
143
- didUpdate: "all" === options.updateSnapshot
144
- };
145
- return summary;
146
- }
147
- function addSnapshotResult(summary, result) {
148
- if (result.added) summary.filesAdded++;
149
- if (result.fileDeleted) summary.filesRemoved++;
150
- if (result.unmatched) summary.filesUnmatched++;
151
- if (result.updated) summary.filesUpdated++;
152
- summary.added += result.added;
153
- summary.matched += result.matched;
154
- summary.unchecked += result.unchecked;
155
- if (result.uncheckedKeys && result.uncheckedKeys.length > 0) summary.uncheckedKeysByFile.push({
156
- filePath: result.filepath,
157
- keys: result.uncheckedKeys
158
- });
159
- summary.unmatched += result.unmatched;
160
- summary.updated += result.updated;
161
- summary.total += result.added + result.matched + result.unmatched + result.updated;
162
- }
163
15
  var external_std_env_ = __webpack_require__("std-env");
164
16
  var src_config = __webpack_require__("./src/config.ts");
165
17
  var stack_trace_parser_esm = __webpack_require__("../../node_modules/.pnpm/stacktrace-parser@0.1.11/node_modules/stacktrace-parser/dist/stack-trace-parser.esm.js");
@@ -381,10 +233,7 @@ export const __webpack_modules__ = {
381
233
  const nameStr = (0, utils.fN)(test);
382
234
  utils.vF.log(`${utils.yW.bgRed(' FAIL ')} ${(0, utils.EQ)(relativePath)} ${nameStr.length ? `${utils.yW.dim(utils.vO)} ${nameStr}` : ''}`);
383
235
  if (test.errors) {
384
- const { printError } = await Promise.all([
385
- __webpack_require__.e("829"),
386
- __webpack_require__.e("704")
387
- ]).then(__webpack_require__.bind(__webpack_require__, "./src/utils/error.ts"));
236
+ const { printError } = await Promise.resolve().then(__webpack_require__.bind(__webpack_require__, "./src/utils/error.ts"));
388
237
  for (const error of test.errors)await printError(error, getSourcemap, rootPath);
389
238
  }
390
239
  }
@@ -503,10 +352,7 @@ export const __webpack_modules__ = {
503
352
  ...testResults.filter((i)=>'fail' === i.status)
504
353
  ];
505
354
  if (0 === failedTests.length) return;
506
- const { parseErrorStacktrace } = await Promise.all([
507
- __webpack_require__.e("829"),
508
- __webpack_require__.e("704")
509
- ]).then(__webpack_require__.bind(__webpack_require__, "./src/utils/error.ts"));
355
+ const { parseErrorStacktrace } = await Promise.resolve().then(__webpack_require__.bind(__webpack_require__, "./src/utils/error.ts"));
510
356
  const logs = [];
511
357
  for (const test of failedTests){
512
358
  const { testPath } = test;
@@ -542,6 +388,128 @@ export const __webpack_modules__ = {
542
388
  function escapeData(s) {
543
389
  return s.replace(/%/g, '%25').replace(/\r/g, '%0D').replace(/\n/g, '%0A').replace(/:/g, '%3A').replace(/,/g, '%2C');
544
390
  }
391
+ var promises_ = __webpack_require__("node:fs/promises");
392
+ var strip_ansi = __webpack_require__("../../node_modules/.pnpm/strip-ansi@7.1.0/node_modules/strip-ansi/index.js");
393
+ var utils_error = __webpack_require__("./src/utils/error.ts");
394
+ class JUnitReporter {
395
+ rootPath;
396
+ outputPath;
397
+ constructor({ rootPath, options: { outputPath } = {} }){
398
+ this.rootPath = rootPath;
399
+ this.outputPath = outputPath;
400
+ }
401
+ sanitizeXml(text) {
402
+ let result = '';
403
+ for (const ch of (0, strip_ansi.A)(text)){
404
+ const cp = ch.codePointAt(0);
405
+ const valid = 0x09 === cp || 0x0a === cp || 0x0d === cp || cp >= 0x20 && cp <= 0xd7ff || cp >= 0xe000 && cp <= 0xfffd || cp >= 0x10000 && cp <= 0x10ffff;
406
+ if (valid) result += ch;
407
+ }
408
+ return result;
409
+ }
410
+ escapeXml(text) {
411
+ const sanitized = this.sanitizeXml(text);
412
+ return sanitized.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&apos;');
413
+ }
414
+ async createJUnitTestCase(test, getSourcemap) {
415
+ const testCase = {
416
+ name: (0, utils.fN)(test),
417
+ classname: (0, external_pathe_.relative)(this.rootPath, test.testPath),
418
+ time: (test.duration || 0) / 1000,
419
+ status: test.status
420
+ };
421
+ if (test.errors && test.errors.length > 0) testCase.errors = await Promise.all(test.errors.map(async (error)=>{
422
+ let details = `${error.message}${error.diff ? `\n${error.diff}` : ''}`;
423
+ const stackFrames = error.stack ? await (0, utils_error.parseErrorStacktrace)({
424
+ stack: error.stack,
425
+ fullStack: error.fullStack,
426
+ getSourcemap
427
+ }) : [];
428
+ if (stackFrames[0]) details += `\n${(0, utils_error.C)(stackFrames[0], this.rootPath)}`;
429
+ return {
430
+ message: this.escapeXml(error.message),
431
+ type: error.name || 'Error',
432
+ details: this.escapeXml(details)
433
+ };
434
+ }));
435
+ return testCase;
436
+ }
437
+ async createJUnitTestSuite(fileResult, getSourcemap) {
438
+ const testCases = await Promise.all(fileResult.results.map(async (test)=>this.createJUnitTestCase(test, getSourcemap)));
439
+ const failures = testCases.filter((test)=>'fail' === test.status).length;
440
+ const errors = 0;
441
+ const skipped = testCases.filter((test)=>'skip' === test.status || 'todo' === test.status).length;
442
+ const totalTime = testCases.reduce((sum, test)=>sum + test.time, 0);
443
+ return {
444
+ name: (0, external_pathe_.relative)(this.rootPath, fileResult.testPath),
445
+ tests: testCases.length,
446
+ failures,
447
+ errors,
448
+ skipped,
449
+ time: totalTime,
450
+ timestamp: new Date().toISOString(),
451
+ testcases: testCases
452
+ };
453
+ }
454
+ generateJUnitXml(report) {
455
+ const xmlDeclaration = '<?xml version="1.0" encoding="UTF-8"?>';
456
+ const testsuitesXml = `
457
+ <testsuites name="${this.escapeXml(report.testsuites.name)}" tests="${report.testsuites.tests}" failures="${report.testsuites.failures}" errors="${report.testsuites.errors}" skipped="${report.testsuites.skipped}" time="${report.testsuites.time}" timestamp="${this.escapeXml(report.testsuites.timestamp)}">`;
458
+ const testsuiteXmls = report.testsuites.testsuite.map((suite)=>{
459
+ const testsuiteStart = `
460
+ <testsuite name="${this.escapeXml(suite.name)}" tests="${suite.tests}" failures="${suite.failures}" errors="${suite.errors}" skipped="${suite.skipped}" time="${suite.time}" timestamp="${this.escapeXml(suite.timestamp)}">`;
461
+ const testcaseXmls = suite.testcases.map((testcase)=>{
462
+ let testcaseXml = `
463
+ <testcase name="${this.escapeXml(testcase.name)}" classname="${this.escapeXml(testcase.classname)}" time="${testcase.time}">`;
464
+ if ('skip' === testcase.status || 'todo' === testcase.status) testcaseXml += `
465
+ <skipped/>`;
466
+ else if ('fail' === testcase.status && testcase.errors) testcase.errors.forEach((error)=>{
467
+ testcaseXml += `
468
+ <failure message="${error.message}" type="${error.type}">${error.details || ''}</failure>`;
469
+ });
470
+ testcaseXml += `
471
+ </testcase>`;
472
+ return testcaseXml;
473
+ }).join('');
474
+ const testsuiteEnd = `
475
+ </testsuite>`;
476
+ return testsuiteStart + testcaseXmls + testsuiteEnd;
477
+ }).join('');
478
+ const testsuitesEnd = `
479
+ </testsuites>`;
480
+ return xmlDeclaration + testsuitesXml + testsuiteXmls + testsuitesEnd;
481
+ }
482
+ async onTestRunEnd({ results, testResults, duration, getSourcemap }) {
483
+ const testSuites = await Promise.all(results.map(async (fileResult)=>this.createJUnitTestSuite(fileResult, getSourcemap)));
484
+ const totalTests = testResults.length;
485
+ const totalFailures = testResults.filter((test)=>'fail' === test.status).length;
486
+ const totalErrors = 0;
487
+ const totalSkipped = testResults.filter((test)=>'skip' === test.status || 'todo' === test.status).length;
488
+ const totalTime = duration.testTime / 1000;
489
+ const report = {
490
+ testsuites: {
491
+ name: 'rstest tests',
492
+ tests: totalTests,
493
+ failures: totalFailures,
494
+ errors: totalErrors,
495
+ skipped: totalSkipped,
496
+ time: totalTime,
497
+ timestamp: new Date().toISOString(),
498
+ testsuite: testSuites
499
+ }
500
+ };
501
+ const xmlContent = this.generateJUnitXml(report);
502
+ if (this.outputPath) try {
503
+ await (0, promises_.writeFile)(this.outputPath, xmlContent, 'utf-8');
504
+ console.log(`JUnit XML report written to: ${this.outputPath}`);
505
+ } catch (error) {
506
+ console.error(`Failed to write JUnit XML report to ${this.outputPath}:`, error);
507
+ console.log('JUnit XML Report:');
508
+ console.log(xmlContent);
509
+ }
510
+ else console.log(xmlContent);
511
+ }
512
+ }
545
513
  class VerboseReporter extends DefaultReporter {
546
514
  onTestFileResult(test) {
547
515
  this.statusRenderer?.removeRunningModule(test.testPath);
@@ -551,7 +519,6 @@ export const __webpack_modules__ = {
551
519
  for (const result of test.results)logCase(result, slowTestThreshold);
552
520
  }
553
521
  }
554
- var helper = __webpack_require__("./src/utils/helper.ts");
555
522
  function formatEnvironmentName(name) {
556
523
  return name.replace(/[^a-zA-Z0-9\-_$]/g, '_');
557
524
  }
@@ -577,24 +544,29 @@ export const __webpack_modules__ = {
577
544
  this.command = command;
578
545
  this.fileFilters = fileFilters;
579
546
  this.configFilePath = configFilePath;
580
- const rootPath = userConfig.root ? (0, helper.FI)(cwd, userConfig.root) : cwd;
547
+ const rootPath = userConfig.root ? (0, utils.FI)(cwd, userConfig.root) : cwd;
581
548
  const rstestConfig = (0, src_config.wX)(userConfig);
582
549
  const reporters = 'list' !== command ? createReporters(rstestConfig.reporters, {
583
550
  rootPath,
584
551
  config: rstestConfig
585
552
  }) : [];
586
- const snapshotManager = new SnapshotManager({
553
+ const snapshotManager = new manager.CW({
587
554
  updateSnapshot: rstestConfig.update ? 'all' : external_std_env_.isCI ? 'none' : 'new'
588
555
  });
589
556
  this.reporters = reporters;
590
557
  this.snapshotManager = snapshotManager;
591
- this.version = "0.3.1";
558
+ this.version = "0.3.3";
592
559
  this.rootPath = rootPath;
593
560
  this.originalConfig = userConfig;
594
561
  this.normalizedConfig = rstestConfig;
595
562
  this.projects = projects.length ? projects.map((project)=>{
596
563
  const config = (0, src_config.wX)(project.config);
597
564
  config.isolate = rstestConfig.isolate;
565
+ config.source ??= {};
566
+ if (!config.source.tsconfigPath) {
567
+ const tsconfigPath = (0, external_pathe_.join)(config.root, utils.WB);
568
+ if ((0, external_node_fs_.existsSync)(tsconfigPath)) config.source.tsconfigPath = tsconfigPath;
569
+ }
598
570
  return {
599
571
  configFilePath: project.configFilePath,
600
572
  rootPath: config.root,
@@ -631,10 +603,11 @@ export const __webpack_modules__ = {
631
603
  const reportersMap = {
632
604
  default: DefaultReporter,
633
605
  verbose: VerboseReporter,
634
- 'github-actions': GithubActionsReporter
606
+ 'github-actions': GithubActionsReporter,
607
+ junit: JUnitReporter
635
608
  };
636
609
  function createReporters(reporters, initOptions = {}) {
637
- const result = (0, helper.bg)(reporters).map((reporter)=>{
610
+ const result = (0, utils.bg)(reporters).map((reporter)=>{
638
611
  if ('string' == typeof reporter || Array.isArray(reporter)) {
639
612
  const [name, options = {}] = 'string' == typeof reporter ? [
640
613
  reporter,
@@ -681,5 +654,103 @@ export const __webpack_modules__ = {
681
654
  listTests
682
655
  };
683
656
  }
657
+ },
658
+ "./src/utils/error.ts": function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
659
+ __webpack_require__.d(__webpack_exports__, {
660
+ C: ()=>formatStack,
661
+ parseErrorStacktrace: ()=>parseErrorStacktrace,
662
+ printError: ()=>printError
663
+ });
664
+ var node_fs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("node:fs");
665
+ var _jridgewell_trace_mapping__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("../../node_modules/.pnpm/@jridgewell+trace-mapping@0.3.30/node_modules/@jridgewell/trace-mapping/dist/trace-mapping.mjs");
666
+ var stacktrace_parser__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__("../../node_modules/.pnpm/stacktrace-parser@0.1.11/node_modules/stacktrace-parser/dist/stack-trace-parser.esm.js");
667
+ var _utils__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__("./src/utils/index.ts");
668
+ async function printError(error, getSourcemap, rootPath) {
669
+ const errorName = error.name || 'Unknown Error';
670
+ if (error.message.includes('Vitest failed to access its internal state')) {
671
+ const tips = [
672
+ 'Error: not support import `vitest` in Rstest test environment.\n',
673
+ 'Solution:',
674
+ ` - Update your code to use imports from "${_utils__WEBPACK_IMPORTED_MODULE_3__.yW.yellow('@rstest/core')}" instead of "${_utils__WEBPACK_IMPORTED_MODULE_3__.yW.yellow('vitest')}".`,
675
+ ' - Enable `globals` configuration and use global API.'
676
+ ];
677
+ _utils__WEBPACK_IMPORTED_MODULE_3__.vF.log(`${_utils__WEBPACK_IMPORTED_MODULE_3__.yW.red(tips.join('\n'))}\n`);
678
+ return;
679
+ }
680
+ _utils__WEBPACK_IMPORTED_MODULE_3__.vF.log(`${_utils__WEBPACK_IMPORTED_MODULE_3__.yW.red(_utils__WEBPACK_IMPORTED_MODULE_3__.yW.bold(errorName))}${_utils__WEBPACK_IMPORTED_MODULE_3__.yW.red(`: ${error.message}`)}\n`);
681
+ if (error.diff) {
682
+ _utils__WEBPACK_IMPORTED_MODULE_3__.vF.log(error.diff);
683
+ _utils__WEBPACK_IMPORTED_MODULE_3__.vF.log();
684
+ }
685
+ if (error.stack) {
686
+ const stackFrames = await parseErrorStacktrace({
687
+ stack: error.stack,
688
+ fullStack: error.fullStack,
689
+ getSourcemap
690
+ });
691
+ if (!stackFrames.length && error.stack.length) _utils__WEBPACK_IMPORTED_MODULE_3__.vF.log(_utils__WEBPACK_IMPORTED_MODULE_3__.yW.gray("No error stack found, set 'DEBUG=rstest' to show fullStack."));
692
+ if (stackFrames[0]) await printCodeFrame(stackFrames[0]);
693
+ printStack(stackFrames, rootPath);
694
+ }
695
+ }
696
+ async function printCodeFrame(frame) {
697
+ const filePath = frame.file?.startsWith('file') ? new URL(frame.file) : frame.file;
698
+ if (!filePath) return;
699
+ const source = node_fs__WEBPACK_IMPORTED_MODULE_0__["default"].existsSync(filePath) ? node_fs__WEBPACK_IMPORTED_MODULE_0__["default"].readFileSync(filePath, 'utf-8') : void 0;
700
+ if (!source) return;
701
+ const { codeFrameColumns } = await __webpack_require__.e("171").then(__webpack_require__.bind(__webpack_require__, "../../node_modules/.pnpm/@babel+code-frame@7.27.1/node_modules/@babel/code-frame/lib/index.js"));
702
+ const result = codeFrameColumns(source, {
703
+ start: {
704
+ line: frame.lineNumber,
705
+ column: frame.column
706
+ }
707
+ }, {
708
+ highlightCode: true,
709
+ linesBelow: 2
710
+ });
711
+ _utils__WEBPACK_IMPORTED_MODULE_3__.vF.log(result);
712
+ _utils__WEBPACK_IMPORTED_MODULE_3__.vF.log('');
713
+ }
714
+ function formatStack(frame, rootPath) {
715
+ return '<unknown>' !== frame.methodName ? `at ${frame.methodName} (${(0, _utils__WEBPACK_IMPORTED_MODULE_3__.XJ)(rootPath, frame.file)}:${frame.lineNumber}:${frame.column})` : `at ${(0, _utils__WEBPACK_IMPORTED_MODULE_3__.XJ)(rootPath, frame.file)}:${frame.lineNumber}:${frame.column}`;
716
+ }
717
+ function printStack(stackFrames, rootPath) {
718
+ for (const frame of stackFrames)_utils__WEBPACK_IMPORTED_MODULE_3__.vF.log(_utils__WEBPACK_IMPORTED_MODULE_3__.yW.gray(` ${formatStack(frame, rootPath)}`));
719
+ stackFrames.length && _utils__WEBPACK_IMPORTED_MODULE_3__.vF.log();
720
+ }
721
+ const stackIgnores = [
722
+ /\/@rstest\/core/,
723
+ /rstest\/packages\/core\/dist/,
724
+ /node_modules\/tinypool/,
725
+ /node_modules\/chai/,
726
+ /node_modules\/@vitest\/expect/,
727
+ /node_modules\/@vitest\/snapshot/,
728
+ /node:\w+/,
729
+ /webpack\/runtime/,
730
+ /webpack\\runtime/,
731
+ '<anonymous>'
732
+ ];
733
+ async function parseErrorStacktrace({ stack, getSourcemap, fullStack = (0, _utils__WEBPACK_IMPORTED_MODULE_3__._o)() }) {
734
+ const stackFrames = await Promise.all((0, stacktrace_parser__WEBPACK_IMPORTED_MODULE_2__.q)(stack).filter((frame)=>fullStack ? true : frame.file && !stackIgnores.some((entry)=>frame.file?.match(entry))).map(async (frame)=>{
735
+ const sourcemap = getSourcemap(frame.file);
736
+ if (sourcemap) {
737
+ const traceMap = new _jridgewell_trace_mapping__WEBPACK_IMPORTED_MODULE_1__.YX(sourcemap);
738
+ const { line, column, source, name } = (0, _jridgewell_trace_mapping__WEBPACK_IMPORTED_MODULE_1__.sP)(traceMap, {
739
+ line: frame.lineNumber,
740
+ column: frame.column
741
+ });
742
+ if (!source) return null;
743
+ return {
744
+ ...frame,
745
+ file: source,
746
+ lineNumber: line,
747
+ name,
748
+ column
749
+ };
750
+ }
751
+ return frame;
752
+ })).then((frames)=>frames.filter((frame)=>null !== frame));
753
+ return stackFrames;
754
+ }
684
755
  }
685
756
  };
package/dist/33.js CHANGED
@@ -181,7 +181,10 @@ export const __webpack_modules__ = {
181
181
  }));
182
182
  const rsbuildInstance = await (0, rsbuild.zh)(context, globTestSourceEntries, setupFiles);
183
183
  const { getRsbuildStats, closeServer } = await (0, rsbuild.XD)({
184
- normalizedConfig: context.normalizedConfig,
184
+ inspectedConfig: {
185
+ ...context.normalizedConfig,
186
+ projects: context.projects.map((p)=>p.normalizedConfig)
187
+ },
185
188
  globTestSourceEntries: 'watch' === command ? globTestSourceEntries : async (name)=>{
186
189
  if (entriesCache.has(name)) return entriesCache.get(name).entries;
187
190
  return globTestSourceEntries(name);
package/dist/350.js CHANGED
@@ -9,17 +9,19 @@ export const __webpack_modules__ = {
9
9
  __webpack_require__.d(__webpack_exports__, {
10
10
  environment: ()=>environment
11
11
  });
12
- var _utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/runtime/worker/env/utils.ts");
12
+ var _util__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/runtime/util.ts");
13
+ var _utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./src/runtime/worker/env/utils.ts");
13
14
  const environment = {
14
15
  name: 'happy-dom',
15
16
  async setup (global, { happyDom = {} }) {
17
+ (0, _util__WEBPACK_IMPORTED_MODULE_0__.DW)('happy-dom');
16
18
  const { Window } = await import("happy-dom");
17
19
  const win = new Window({
18
20
  ...happyDom,
19
21
  url: happyDom.url || 'http://localhost:3000',
20
22
  console: console && global.console ? global.console : void 0
21
23
  });
22
- const cleanupGlobal = (0, _utils__WEBPACK_IMPORTED_MODULE_0__.p5)(global, win, {
24
+ const cleanupGlobal = (0, _utils__WEBPACK_IMPORTED_MODULE_1__.p5)(global, win, {
23
25
  additionalKeys: [
24
26
  'Request',
25
27
  'Response',
@@ -27,7 +29,7 @@ export const __webpack_modules__ = {
27
29
  'fetch'
28
30
  ]
29
31
  });
30
- const cleanupHandler = (0, _utils__WEBPACK_IMPORTED_MODULE_0__.d1)(global);
32
+ const cleanupHandler = (0, _utils__WEBPACK_IMPORTED_MODULE_1__.d1)(global);
31
33
  return {
32
34
  async teardown () {
33
35
  cleanupHandler();
@@ -1,10 +1,103 @@
1
1
  import 'module';
2
2
  /*#__PURE__*/ import.meta.url;
3
- export const __webpack_id__ = "829";
3
+ export const __webpack_id__ = "465";
4
4
  export const __webpack_ids__ = [
5
- "829"
5
+ "465"
6
6
  ];
7
7
  export const __webpack_modules__ = {
8
+ "../../node_modules/.pnpm/stacktrace-parser@0.1.11/node_modules/stacktrace-parser/dist/stack-trace-parser.esm.js": function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
9
+ __webpack_require__.d(__webpack_exports__, {
10
+ q: ()=>parse
11
+ });
12
+ var UNKNOWN_FUNCTION = '<unknown>';
13
+ function parse(stackString) {
14
+ var lines = stackString.split('\n');
15
+ return lines.reduce(function(stack, line) {
16
+ var parseResult = parseChrome(line) || parseWinjs(line) || parseGecko(line) || parseNode(line) || parseJSC(line);
17
+ if (parseResult) stack.push(parseResult);
18
+ return stack;
19
+ }, []);
20
+ }
21
+ var chromeRe = /^\s*at (.*?) ?\(((?:file|https?|blob|chrome-extension|native|eval|webpack|rsc|<anonymous>|\/|[a-z]:\\|\\\\).*?)(?::(\d+))?(?::(\d+))?\)?\s*$/i;
22
+ var chromeEvalRe = /\((\S*)(?::(\d+))(?::(\d+))\)/;
23
+ function parseChrome(line) {
24
+ var parts = chromeRe.exec(line);
25
+ if (!parts) return null;
26
+ var isNative = parts[2] && 0 === parts[2].indexOf('native');
27
+ var isEval = parts[2] && 0 === parts[2].indexOf('eval');
28
+ var submatch = chromeEvalRe.exec(parts[2]);
29
+ if (isEval && null != submatch) {
30
+ parts[2] = submatch[1];
31
+ parts[3] = submatch[2];
32
+ parts[4] = submatch[3];
33
+ }
34
+ return {
35
+ file: isNative ? null : parts[2],
36
+ methodName: parts[1] || UNKNOWN_FUNCTION,
37
+ arguments: isNative ? [
38
+ parts[2]
39
+ ] : [],
40
+ lineNumber: parts[3] ? +parts[3] : null,
41
+ column: parts[4] ? +parts[4] : null
42
+ };
43
+ }
44
+ var winjsRe = /^\s*at (?:((?:\[object object\])?.+) )?\(?((?:file|ms-appx|https?|webpack|rsc|blob):.*?):(\d+)(?::(\d+))?\)?\s*$/i;
45
+ function parseWinjs(line) {
46
+ var parts = winjsRe.exec(line);
47
+ if (!parts) return null;
48
+ return {
49
+ file: parts[2],
50
+ methodName: parts[1] || UNKNOWN_FUNCTION,
51
+ arguments: [],
52
+ lineNumber: +parts[3],
53
+ column: parts[4] ? +parts[4] : null
54
+ };
55
+ }
56
+ var geckoRe = /^\s*(.*?)(?:\((.*?)\))?(?:^|@)((?:file|https?|blob|chrome|webpack|rsc|resource|\[native).*?|[^@]*bundle)(?::(\d+))?(?::(\d+))?\s*$/i;
57
+ var geckoEvalRe = /(\S+) line (\d+)(?: > eval line \d+)* > eval/i;
58
+ function parseGecko(line) {
59
+ var parts = geckoRe.exec(line);
60
+ if (!parts) return null;
61
+ var isEval = parts[3] && parts[3].indexOf(' > eval') > -1;
62
+ var submatch = geckoEvalRe.exec(parts[3]);
63
+ if (isEval && null != submatch) {
64
+ parts[3] = submatch[1];
65
+ parts[4] = submatch[2];
66
+ parts[5] = null;
67
+ }
68
+ return {
69
+ file: parts[3],
70
+ methodName: parts[1] || UNKNOWN_FUNCTION,
71
+ arguments: parts[2] ? parts[2].split(',') : [],
72
+ lineNumber: parts[4] ? +parts[4] : null,
73
+ column: parts[5] ? +parts[5] : null
74
+ };
75
+ }
76
+ var javaScriptCoreRe = /^\s*(?:([^@]*)(?:\((.*?)\))?@)?(\S.*?):(\d+)(?::(\d+))?\s*$/i;
77
+ function parseJSC(line) {
78
+ var parts = javaScriptCoreRe.exec(line);
79
+ if (!parts) return null;
80
+ return {
81
+ file: parts[3],
82
+ methodName: parts[1] || UNKNOWN_FUNCTION,
83
+ arguments: [],
84
+ lineNumber: +parts[4],
85
+ column: parts[5] ? +parts[5] : null
86
+ };
87
+ }
88
+ var nodeRe = /^\s*at (?:((?:\[object object\])?[^\\/]+(?: \[as \S+\])?) )?\(?(.*?):(\d+)(?::(\d+))?\)?\s*$/i;
89
+ function parseNode(line) {
90
+ var parts = nodeRe.exec(line);
91
+ if (!parts) return null;
92
+ return {
93
+ file: parts[2],
94
+ methodName: parts[1] || UNKNOWN_FUNCTION,
95
+ arguments: [],
96
+ lineNumber: +parts[3],
97
+ column: parts[4] ? +parts[4] : null
98
+ };
99
+ }
100
+ },
8
101
  "../../node_modules/.pnpm/@jridgewell+trace-mapping@0.3.30/node_modules/@jridgewell/trace-mapping/dist/trace-mapping.mjs": function(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) {
9
102
  __webpack_require__.d(__webpack_exports__, {
10
103
  YX: ()=>TraceMap,
@@ -414,5 +507,86 @@ export const __webpack_modules__ = {
414
507
  if (-1 === index || index === segments.length) return -1;
415
508
  return index;
416
509
  }
510
+ },
511
+ "../../node_modules/.pnpm/@vitest+snapshot@3.2.4/node_modules/@vitest/snapshot/dist/manager.js": function(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) {
512
+ __webpack_require__.d(__webpack_exports__, {
513
+ CW: ()=>SnapshotManager
514
+ });
515
+ var pathe__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("pathe");
516
+ class SnapshotManager {
517
+ summary;
518
+ extension = ".snap";
519
+ constructor(options){
520
+ this.options = options;
521
+ this.clear();
522
+ }
523
+ clear() {
524
+ this.summary = emptySummary(this.options);
525
+ }
526
+ add(result) {
527
+ addSnapshotResult(this.summary, result);
528
+ }
529
+ resolvePath(testPath, context) {
530
+ const resolver = this.options.resolveSnapshotPath || (()=>(0, pathe__WEBPACK_IMPORTED_MODULE_0__.join)((0, pathe__WEBPACK_IMPORTED_MODULE_0__.join)((0, pathe__WEBPACK_IMPORTED_MODULE_0__.dirname)(testPath), "__snapshots__"), `${(0, pathe__WEBPACK_IMPORTED_MODULE_0__.basename)(testPath)}${this.extension}`));
531
+ const path = resolver(testPath, this.extension, context);
532
+ return path;
533
+ }
534
+ resolveRawPath(testPath, rawPath) {
535
+ return (0, pathe__WEBPACK_IMPORTED_MODULE_0__.isAbsolute)(rawPath) ? rawPath : (0, pathe__WEBPACK_IMPORTED_MODULE_0__.resolve)((0, pathe__WEBPACK_IMPORTED_MODULE_0__.dirname)(testPath), rawPath);
536
+ }
537
+ }
538
+ function emptySummary(options) {
539
+ const summary = {
540
+ added: 0,
541
+ failure: false,
542
+ filesAdded: 0,
543
+ filesRemoved: 0,
544
+ filesRemovedList: [],
545
+ filesUnmatched: 0,
546
+ filesUpdated: 0,
547
+ matched: 0,
548
+ total: 0,
549
+ unchecked: 0,
550
+ uncheckedKeysByFile: [],
551
+ unmatched: 0,
552
+ updated: 0,
553
+ didUpdate: "all" === options.updateSnapshot
554
+ };
555
+ return summary;
556
+ }
557
+ function addSnapshotResult(summary, result) {
558
+ if (result.added) summary.filesAdded++;
559
+ if (result.fileDeleted) summary.filesRemoved++;
560
+ if (result.unmatched) summary.filesUnmatched++;
561
+ if (result.updated) summary.filesUpdated++;
562
+ summary.added += result.added;
563
+ summary.matched += result.matched;
564
+ summary.unchecked += result.unchecked;
565
+ if (result.uncheckedKeys && result.uncheckedKeys.length > 0) summary.uncheckedKeysByFile.push({
566
+ filePath: result.filepath,
567
+ keys: result.uncheckedKeys
568
+ });
569
+ summary.unmatched += result.unmatched;
570
+ summary.updated += result.updated;
571
+ summary.total += result.added + result.matched + result.unmatched + result.updated;
572
+ }
573
+ },
574
+ "../../node_modules/.pnpm/strip-ansi@7.1.0/node_modules/strip-ansi/index.js": function(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) {
575
+ __webpack_require__.d(__webpack_exports__, {
576
+ A: ()=>stripAnsi
577
+ });
578
+ function ansiRegex({ onlyFirst = false } = {}) {
579
+ const ST = '(?:\\u0007|\\u001B\\u005C|\\u009C)';
580
+ const pattern = [
581
+ `[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?${ST})`,
582
+ '(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]))'
583
+ ].join('|');
584
+ return new RegExp(pattern, onlyFirst ? void 0 : 'g');
585
+ }
586
+ const regex = ansiRegex();
587
+ function stripAnsi(string) {
588
+ if ('string' != typeof string) throw new TypeError(`Expected a \`string\`, got \`${typeof string}\``);
589
+ return string.replace(regex, '');
590
+ }
417
591
  }
418
592
  };
package/dist/711.js CHANGED
@@ -9,10 +9,12 @@ export const __webpack_modules__ = {
9
9
  __webpack_require__.d(__webpack_exports__, {
10
10
  environment: ()=>environment
11
11
  });
12
- var _utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/runtime/worker/env/utils.ts");
12
+ var _util__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/runtime/util.ts");
13
+ var _utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./src/runtime/worker/env/utils.ts");
13
14
  const environment = {
14
15
  name: 'jsdom',
15
16
  async setup (global, { jsdom = {} }) {
17
+ (0, _util__WEBPACK_IMPORTED_MODULE_0__.DW)('jsdom');
16
18
  const { CookieJar, JSDOM, ResourceLoader, VirtualConsole } = await import("jsdom");
17
19
  const { html = '<!DOCTYPE html>', userAgent, url = 'http://localhost:3000', contentType = 'text/html', pretendToBeVisual = true, includeNodeLocations = false, runScripts = 'dangerously', resources, console = false, cookieJar = false, ...restOptions } = jsdom;
18
20
  const dom = new JSDOM(html, {
@@ -29,8 +31,8 @@ export const __webpack_modules__ = {
29
31
  userAgent,
30
32
  ...restOptions
31
33
  });
32
- const cleanupGlobal = (0, _utils__WEBPACK_IMPORTED_MODULE_0__.p5)(global, dom.window);
33
- const cleanupHandler = (0, _utils__WEBPACK_IMPORTED_MODULE_0__.d1)(global);
34
+ const cleanupGlobal = (0, _utils__WEBPACK_IMPORTED_MODULE_1__.p5)(global, dom.window);
35
+ const cleanupHandler = (0, _utils__WEBPACK_IMPORTED_MODULE_1__.d1)(global);
34
36
  return {
35
37
  teardown () {
36
38
  cleanupHandler();
package/dist/85.js CHANGED
@@ -1806,7 +1806,7 @@ export const __webpack_modules__ = {
1806
1806
  configurable: true
1807
1807
  });
1808
1808
  const rstest = createRstestUtilities(workerState);
1809
- return {
1809
+ const runtime = {
1810
1810
  runner,
1811
1811
  api: {
1812
1812
  ...runnerAPI,
@@ -1816,6 +1816,8 @@ export const __webpack_modules__ = {
1816
1816
  rs: rstest
1817
1817
  }
1818
1818
  };
1819
+ globalThis.RSTEST_API = runtime.api;
1820
+ return runtime;
1819
1821
  };
1820
1822
  },
1821
1823
  "./src/utils/index.ts": function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
package/dist/971.js CHANGED
@@ -41,7 +41,10 @@ export const __webpack_modules__ = {
41
41
  const rsbuildInstance = await (0, _rsbuild__WEBPACK_IMPORTED_MODULE_4__.zh)(context, globTestSourceEntries, setupFiles);
42
42
  const { getRsbuildStats, closeServer } = await (0, _rsbuild__WEBPACK_IMPORTED_MODULE_4__.XD)({
43
43
  globTestSourceEntries,
44
- normalizedConfig: context.normalizedConfig,
44
+ inspectedConfig: {
45
+ ...context.normalizedConfig,
46
+ projects: context.projects.map((p)=>p.normalizedConfig)
47
+ },
45
48
  setupFiles,
46
49
  rsbuildInstance,
47
50
  rootPath
@@ -89,10 +92,7 @@ export const __webpack_modules__ = {
89
92
  const hasError = list.some((file)=>file.errors?.length);
90
93
  const showProject = context.projects.length > 1;
91
94
  if (hasError) {
92
- const { printError } = await Promise.all([
93
- __webpack_require__.e("829"),
94
- __webpack_require__.e("704")
95
- ]).then(__webpack_require__.bind(__webpack_require__, "./src/utils/error.ts"));
95
+ const { printError } = await Promise.resolve().then(__webpack_require__.bind(__webpack_require__, "./src/utils/error.ts"));
96
96
  process.exitCode = 1;
97
97
  for (const file of list){
98
98
  const relativePath = (0, node_path__WEBPACK_IMPORTED_MODULE_1__.relative)(rootPath, file.testPath);
package/dist/985.js CHANGED
@@ -43,6 +43,7 @@ export const __webpack_modules__ = {
43
43
  },
44
44
  tools: {
45
45
  rspack: (config, { isProd, rspack })=>{
46
+ config.context = rootPath;
46
47
  config.mode = isProd ? 'production' : 'development';
47
48
  config.output ??= {};
48
49
  config.output.iife = false;
@@ -457,6 +458,7 @@ global.__rstest_clean_core_cache__ = __rstest_clean_core_cache__;
457
458
  const rsbuildInstance = await (0, core_.createRsbuild)({
458
459
  callerName: 'rstest',
459
460
  rsbuildConfig: {
461
+ root: context.rootPath,
460
462
  server: {
461
463
  printUrls: false,
462
464
  strictPort: false,
@@ -544,7 +546,7 @@ global.__rstest_clean_core_cache__ = __rstest_clean_core_cache__;
544
546
  deletedEntries
545
547
  };
546
548
  };
547
- const createRsbuildServer = async ({ globTestSourceEntries, setupFiles, rsbuildInstance, normalizedConfig })=>{
549
+ const createRsbuildServer = async ({ globTestSourceEntries, setupFiles, rsbuildInstance, inspectedConfig })=>{
548
550
  let rspackCompiler;
549
551
  const rstestCompilerPlugin = {
550
552
  name: 'rstest:compiler',
@@ -563,7 +565,7 @@ global.__rstest_clean_core_cache__ = __rstest_clean_core_cache__;
563
565
  if ((0, utils._o)()) await rsbuildInstance.inspectConfig({
564
566
  writeToDisk: true,
565
567
  extraConfigs: {
566
- rstest: normalizedConfig
568
+ rstest: inspectedConfig
567
569
  }
568
570
  });
569
571
  if (!rspackCompiler) throw new Error('rspackCompiler was not initialized');
package/dist/index.js CHANGED
@@ -2684,7 +2684,10 @@ ${section.body}` : section.body).join("\n\n"));
2684
2684
  try {
2685
2685
  const { initCli } = await __webpack_require__.e("223").then(__webpack_require__.bind(__webpack_require__, "./src/cli/init.ts"));
2686
2686
  const { config, configFilePath, projects } = await initCli(options);
2687
- const { createRstest } = await __webpack_require__.e("12").then(__webpack_require__.bind(__webpack_require__, "./src/core/index.ts"));
2687
+ const { createRstest } = await Promise.all([
2688
+ __webpack_require__.e("465"),
2689
+ __webpack_require__.e("263")
2690
+ ]).then(__webpack_require__.bind(__webpack_require__, "./src/core/index.ts"));
2688
2691
  rstest = createRstest({
2689
2692
  config,
2690
2693
  configFilePath,
@@ -2709,7 +2712,7 @@ ${section.body}` : section.body).join("\n\n"));
2709
2712
  function setupCommands() {
2710
2713
  const cli = dist('rstest');
2711
2714
  cli.help();
2712
- cli.version("0.3.1");
2715
+ cli.version("0.3.3");
2713
2716
  applyCommonOptions(cli);
2714
2717
  cli.command('[...filters]', 'run tests').option('-w, --watch', 'Run tests in watch mode').action(async (filters, options)=>{
2715
2718
  (0, prepare.N)();
@@ -2744,7 +2747,10 @@ ${section.body}` : section.body).join("\n\n"));
2744
2747
  try {
2745
2748
  const { initCli } = await __webpack_require__.e("223").then(__webpack_require__.bind(__webpack_require__, "./src/cli/init.ts"));
2746
2749
  const { config, configFilePath, projects } = await initCli(options);
2747
- const { createRstest } = await __webpack_require__.e("12").then(__webpack_require__.bind(__webpack_require__, "./src/core/index.ts"));
2750
+ const { createRstest } = await Promise.all([
2751
+ __webpack_require__.e("465"),
2752
+ __webpack_require__.e("263")
2753
+ ]).then(__webpack_require__.bind(__webpack_require__, "./src/core/index.ts"));
2748
2754
  const rstest = createRstest({
2749
2755
  config,
2750
2756
  configFilePath,
@@ -2779,7 +2785,7 @@ ${section.body}` : section.body).join("\n\n"));
2779
2785
  if (!npm_execpath || npm_execpath.includes('npx-cli.js') || npm_execpath.includes('.bun')) console.log();
2780
2786
  }
2781
2787
  function showRstest() {
2782
- _utils_logger__WEBPACK_IMPORTED_MODULE_0__.vF.greet(" Rstest v0.3.1");
2788
+ _utils_logger__WEBPACK_IMPORTED_MODULE_0__.vF.greet(" Rstest v0.3.3");
2783
2789
  _utils_logger__WEBPACK_IMPORTED_MODULE_0__.vF.log('');
2784
2790
  }
2785
2791
  },
@@ -2880,6 +2886,7 @@ ${section.body}` : section.body).join("\n\n"));
2880
2886
  "./src/utils/constants.ts": function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
2881
2887
  __webpack_require__.d(__webpack_exports__, {
2882
2888
  EJ: ()=>TEMP_RSTEST_OUTPUT_DIR_GLOB,
2889
+ WB: ()=>TS_CONFIG_FILE,
2883
2890
  kv: ()=>DEFAULT_CONFIG_EXTENSIONS,
2884
2891
  t: ()=>DEFAULT_CONFIG_NAME,
2885
2892
  vO: ()=>TEST_DELIMITER,
@@ -2897,6 +2904,7 @@ ${section.body}` : section.body).join("\n\n"));
2897
2904
  '.cjs',
2898
2905
  '.cts'
2899
2906
  ];
2907
+ const TS_CONFIG_FILE = 'tsconfig.json';
2900
2908
  },
2901
2909
  "./src/utils/helper.ts": function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
2902
2910
  __webpack_require__.d(__webpack_exports__, {
@@ -3066,9 +3074,10 @@ ${section.body}` : section.body).join("\n\n"));
3066
3074
  FI: ()=>helper.FI,
3067
3075
  kv: ()=>constants.kv,
3068
3076
  yW: ()=>helper.yW,
3069
- EQ: ()=>prettyTestPath,
3077
+ WB: ()=>constants.WB,
3070
3078
  _o: ()=>logger._o,
3071
3079
  pr: ()=>getSetupFiles,
3080
+ EQ: ()=>prettyTestPath,
3072
3081
  Kv: ()=>helper.Kv,
3073
3082
  zz: ()=>filterProjects,
3074
3083
  mT: ()=>logger.mT,
@@ -3857,8 +3866,42 @@ async function runCLI() {
3857
3866
  }
3858
3867
  }
3859
3868
  var src_config = __webpack_require__("./src/config.ts");
3869
+ const check = (name)=>{
3870
+ if (!globalThis.RSTEST_API?.[name]) throw new Error(`Rstest API '${name}' is not registered yet, please make sure you are running in a rstest environment.`);
3871
+ };
3872
+ const wrapRstestAPI = (name)=>{
3873
+ const fn = (...args)=>{
3874
+ check(name);
3875
+ return globalThis.RSTEST_API[name].call(globalThis.RSTEST_API[name], ...args);
3876
+ };
3877
+ return new Proxy(fn, {
3878
+ get (_target, key, receiver) {
3879
+ check(name);
3880
+ return Reflect.get(globalThis.RSTEST_API?.[name] || {}, key, receiver);
3881
+ }
3882
+ });
3883
+ };
3884
+ const wrapRstestUtilitiesAPI = (name)=>new Proxy({}, {
3885
+ get (_target, key, receiver) {
3886
+ check(name);
3887
+ return Reflect.get(globalThis.RSTEST_API?.[name] || {}, key, receiver);
3888
+ }
3889
+ });
3890
+ const expect = wrapRstestAPI('expect');
3891
+ const assert = wrapRstestAPI('assert');
3892
+ const it = wrapRstestAPI('it');
3893
+ const test = wrapRstestAPI('test');
3894
+ const describe = wrapRstestAPI('describe');
3895
+ const beforeAll = wrapRstestAPI('beforeAll');
3896
+ const afterAll = wrapRstestAPI('afterAll');
3897
+ const beforeEach = wrapRstestAPI('beforeEach');
3898
+ const afterEach = wrapRstestAPI('afterEach');
3899
+ const rstest = wrapRstestUtilitiesAPI('rstest');
3900
+ const rs = wrapRstestUtilitiesAPI('rs');
3901
+ const onTestFinished = wrapRstestAPI('onTestFinished');
3902
+ const onTestFailed = wrapRstestAPI('onTestFailed');
3860
3903
  function defineConfig(config) {
3861
3904
  return config;
3862
3905
  }
3863
3906
  var __webpack_exports__mergeRstestConfig = src_config.ST;
3864
- export { defineConfig, runCLI, __webpack_exports__mergeRstestConfig as mergeRstestConfig };
3907
+ export { afterAll, afterEach, assert, beforeAll, beforeEach, defineConfig, describe, expect, it, onTestFailed, onTestFinished, rs, rstest, runCLI, test, __webpack_exports__mergeRstestConfig as mergeRstestConfig };
package/dist/worker.js CHANGED
@@ -4967,12 +4967,14 @@ var __webpack_modules__ = {
4967
4967
  },
4968
4968
  "./src/runtime/util.ts": function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
4969
4969
  __webpack_require__.d(__webpack_exports__, {
4970
- zH: ()=>setRealTimers,
4970
+ DW: ()=>checkPkgInstalled,
4971
4971
  nD: ()=>formatName,
4972
4972
  o9: ()=>formatTestError,
4973
+ zH: ()=>setRealTimers,
4973
4974
  si: ()=>TestRegisterError,
4974
4975
  rZ: ()=>getRealTimers
4975
4976
  });
4977
+ var external_node_module_ = __webpack_require__("node:module");
4976
4978
  var external_node_util_ = __webpack_require__("node:util");
4977
4979
  var build = __webpack_require__("../../node_modules/.pnpm/jest-diff@30.0.5/node_modules/jest-diff/build/index.js");
4978
4980
  build.DIFF_DELETE;
@@ -5038,6 +5040,22 @@ var __webpack_modules__ = {
5038
5040
  }
5039
5041
  class TestRegisterError extends Error {
5040
5042
  }
5043
+ class RstestError extends Error {
5044
+ fullStack;
5045
+ }
5046
+ function checkPkgInstalled(name) {
5047
+ const require = (0, external_node_module_.createRequire)(import.meta.url);
5048
+ try {
5049
+ require.resolve(name);
5050
+ } catch (error) {
5051
+ if ('MODULE_NOT_FOUND' === error.code) {
5052
+ const error = new RstestError(`Missing dependency "${name}". Please install it first.`);
5053
+ error.fullStack = true;
5054
+ throw error;
5055
+ }
5056
+ throw error;
5057
+ }
5058
+ }
5041
5059
  },
5042
5060
  "./src/runtime/worker/setup.ts": function() {
5043
5061
  const gracefulExit = process.execArgv.some((execArg)=>execArg.startsWith('--perf') || execArg.startsWith('--prof') || execArg.startsWith('--cpu-prof') || execArg.startsWith('--heap-prof') || execArg.startsWith('--diagnostic-dir'));
@@ -5064,7 +5082,9 @@ var __webpack_modules__ = {
5064
5082
  'beforeEach',
5065
5083
  'rstest',
5066
5084
  'rs',
5067
- 'assert'
5085
+ 'assert',
5086
+ 'onTestFinished',
5087
+ 'onTestFailed'
5068
5088
  ];
5069
5089
  },
5070
5090
  "./src/utils/helper.ts": function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
@@ -1062,6 +1062,28 @@ declare interface JestAssertion<T = any> extends jest.Matchers<void, T>, CustomM
1062
1062
  nthReturnedWith: <E>(nthCall: number, value: E) => void;
1063
1063
  }
1064
1064
 
1065
+ declare class JUnitReporter implements Reporter {
1066
+ private rootPath;
1067
+ private outputPath?;
1068
+ constructor({ rootPath, options: { outputPath }, }: {
1069
+ rootPath: string;
1070
+ options?: {
1071
+ outputPath?: string;
1072
+ };
1073
+ });
1074
+ private sanitizeXml;
1075
+ private escapeXml;
1076
+ private createJUnitTestCase;
1077
+ private createJUnitTestSuite;
1078
+ private generateJUnitXml;
1079
+ onTestRunEnd({ results, testResults, duration, getSourcemap, }: {
1080
+ getSourcemap: GetSourcemap;
1081
+ results: TestFileResult[];
1082
+ testResults: TestResult[];
1083
+ duration: Duration;
1084
+ }): Promise<void>;
1085
+ }
1086
+
1065
1087
  declare function matcherHint(matcherName: string, received?: string, expected?: string, options?: MatcherHintOptions): string;
1066
1088
 
1067
1089
  declare interface MatcherHintOptions {
@@ -1654,7 +1676,7 @@ declare type Procedure = (...args: any[]) => any;
1654
1676
 
1655
1677
  declare type Procedure_2 = (...args: any[]) => any;
1656
1678
 
1657
- declare type ProjectConfig = Omit<RstestConfig, 'projects' | 'reporters' | 'pool' | 'isolate'>;
1679
+ export declare type ProjectConfig = Omit<RstestConfig, 'projects' | 'reporters' | 'pool' | 'isolate'>;
1658
1680
 
1659
1681
  declare type ProjectContext = {
1660
1682
  name: string;
@@ -1727,6 +1749,7 @@ declare const reportersMap: {
1727
1749
  default: typeof DefaultReporter;
1728
1750
  verbose: typeof VerboseReporter;
1729
1751
  'github-actions': typeof GithubActionsReporter;
1752
+ junit: typeof JUnitReporter;
1730
1753
  };
1731
1754
 
1732
1755
  declare type ReporterWithOptions<Name extends BuiltInReporterNames = BuiltInReporterNames> = Name extends keyof BuiltinReporterOptions ? [Name, Partial<BuiltinReporterOptions[Name]>] : [Name, Record<string, unknown>];
@@ -985,6 +985,28 @@ declare interface JestAssertion<T = any> extends jest.Matchers<void, T>, CustomM
985
985
  nthReturnedWith: <E>(nthCall: number, value: E) => void;
986
986
  }
987
987
 
988
+ declare class JUnitReporter implements Reporter {
989
+ private rootPath;
990
+ private outputPath?;
991
+ constructor({ rootPath, options: { outputPath }, }: {
992
+ rootPath: string;
993
+ options?: {
994
+ outputPath?: string;
995
+ };
996
+ });
997
+ private sanitizeXml;
998
+ private escapeXml;
999
+ private createJUnitTestCase;
1000
+ private createJUnitTestSuite;
1001
+ private generateJUnitXml;
1002
+ onTestRunEnd({ results, testResults, duration, getSourcemap, }: {
1003
+ getSourcemap: GetSourcemap;
1004
+ results: TestFileResult[];
1005
+ testResults: TestResult[];
1006
+ duration: Duration;
1007
+ }): Promise<void>;
1008
+ }
1009
+
988
1010
  declare function matcherHint(matcherName: string, received?: string, expected?: string, options?: MatcherHintOptions): string;
989
1011
 
990
1012
  declare interface MatcherHintOptions {
@@ -1502,6 +1524,7 @@ declare const reportersMap: {
1502
1524
  default: typeof DefaultReporter;
1503
1525
  verbose: typeof VerboseReporter;
1504
1526
  'github-actions': typeof GithubActionsReporter;
1527
+ junit: typeof JUnitReporter;
1505
1528
  };
1506
1529
 
1507
1530
  declare type ReporterWithOptions<Name extends BuiltInReporterNames = BuiltInReporterNames> = Name extends keyof BuiltinReporterOptions ? [Name, Partial<BuiltinReporterOptions[Name]>] : [Name, Record<string, unknown>];
package/globals.d.ts CHANGED
@@ -10,6 +10,7 @@ declare global {
10
10
  const afterEach: typeof import('@rstest/core')['afterEach'];
11
11
  const onTestFinished: typeof import('@rstest/core')['onTestFinished'];
12
12
  const onTestFailed: typeof import('@rstest/core')['onTestFailed'];
13
+ const rs: typeof import('@rstest/core')['rs'];
13
14
  const rstest: typeof import('@rstest/core')['rstest'];
14
15
  }
15
16
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rstest/core",
3
- "version": "0.3.1",
3
+ "version": "0.3.3",
4
4
  "description": "The Rsbuild-based test tool.",
5
5
  "bugs": {
6
6
  "url": "https://github.com/web-infra-dev/rstest/issues"
@@ -74,6 +74,7 @@
74
74
  "rslog": "^1.2.11",
75
75
  "source-map-support": "^0.5.21",
76
76
  "stacktrace-parser": "0.1.11",
77
+ "strip-ansi": "^7.1.0",
77
78
  "tinyglobby": "^0.2.14",
78
79
  "tinyspy": "^4.0.3",
79
80
  "@rstest/tsconfig": "0.0.1"
package/dist/704.js DELETED
@@ -1,103 +0,0 @@
1
- import 'module';
2
- /*#__PURE__*/ import.meta.url;
3
- export const __webpack_id__ = "704";
4
- export const __webpack_ids__ = [
5
- "704"
6
- ];
7
- export const __webpack_modules__ = {
8
- "./src/utils/error.ts": function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
9
- __webpack_require__.d(__webpack_exports__, {
10
- parseErrorStacktrace: ()=>parseErrorStacktrace,
11
- printError: ()=>printError
12
- });
13
- var node_fs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("node:fs");
14
- var _jridgewell_trace_mapping__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("../../node_modules/.pnpm/@jridgewell+trace-mapping@0.3.30/node_modules/@jridgewell/trace-mapping/dist/trace-mapping.mjs");
15
- var stacktrace_parser__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__("../../node_modules/.pnpm/stacktrace-parser@0.1.11/node_modules/stacktrace-parser/dist/stack-trace-parser.esm.js");
16
- var _utils__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__("./src/utils/index.ts");
17
- async function printError(error, getSourcemap, rootPath) {
18
- const errorName = error.name || 'Unknown Error';
19
- if (error.message.includes('Vitest failed to access its internal state')) {
20
- const tips = [
21
- 'Error: not support import `vitest` in Rstest test environment.\n',
22
- 'Solution:',
23
- ` - Update your code to use imports from "${_utils__WEBPACK_IMPORTED_MODULE_3__.yW.yellow('@rstest/core')}" instead of "${_utils__WEBPACK_IMPORTED_MODULE_3__.yW.yellow('vitest')}".`,
24
- ' - Enable `globals` configuration and use global API.'
25
- ];
26
- _utils__WEBPACK_IMPORTED_MODULE_3__.vF.log(`${_utils__WEBPACK_IMPORTED_MODULE_3__.yW.red(tips.join('\n'))}\n`);
27
- return;
28
- }
29
- _utils__WEBPACK_IMPORTED_MODULE_3__.vF.log(`${_utils__WEBPACK_IMPORTED_MODULE_3__.yW.red(_utils__WEBPACK_IMPORTED_MODULE_3__.yW.bold(errorName))}${_utils__WEBPACK_IMPORTED_MODULE_3__.yW.red(`: ${error.message}`)}\n`);
30
- if (error.diff) {
31
- _utils__WEBPACK_IMPORTED_MODULE_3__.vF.log(error.diff);
32
- _utils__WEBPACK_IMPORTED_MODULE_3__.vF.log();
33
- }
34
- if (error.stack) {
35
- const stackFrames = await parseErrorStacktrace({
36
- stack: error.stack,
37
- fullStack: error.fullStack,
38
- getSourcemap
39
- });
40
- if (stackFrames[0]) await printCodeFrame(stackFrames[0]);
41
- printStack(stackFrames, rootPath);
42
- }
43
- }
44
- async function printCodeFrame(frame) {
45
- const filePath = frame.file?.startsWith('file') ? new URL(frame.file) : frame.file;
46
- if (!filePath) return;
47
- const source = node_fs__WEBPACK_IMPORTED_MODULE_0__["default"].existsSync(filePath) ? node_fs__WEBPACK_IMPORTED_MODULE_0__["default"].readFileSync(filePath, 'utf-8') : void 0;
48
- if (!source) return;
49
- const { codeFrameColumns } = await __webpack_require__.e("171").then(__webpack_require__.bind(__webpack_require__, "../../node_modules/.pnpm/@babel+code-frame@7.27.1/node_modules/@babel/code-frame/lib/index.js"));
50
- const result = codeFrameColumns(source, {
51
- start: {
52
- line: frame.lineNumber,
53
- column: frame.column
54
- }
55
- }, {
56
- highlightCode: true,
57
- linesBelow: 2
58
- });
59
- _utils__WEBPACK_IMPORTED_MODULE_3__.vF.log(result);
60
- _utils__WEBPACK_IMPORTED_MODULE_3__.vF.log('');
61
- }
62
- function printStack(stackFrames, rootPath) {
63
- for (const frame of stackFrames){
64
- const msg = '<unknown>' !== frame.methodName ? `at ${frame.methodName} (${(0, _utils__WEBPACK_IMPORTED_MODULE_3__.XJ)(rootPath, frame.file)}:${frame.lineNumber}:${frame.column})` : `at ${(0, _utils__WEBPACK_IMPORTED_MODULE_3__.XJ)(rootPath, frame.file)}:${frame.lineNumber}:${frame.column}`;
65
- _utils__WEBPACK_IMPORTED_MODULE_3__.vF.log(_utils__WEBPACK_IMPORTED_MODULE_3__.yW.gray(` ${msg}`));
66
- }
67
- stackFrames.length && _utils__WEBPACK_IMPORTED_MODULE_3__.vF.log();
68
- }
69
- const stackIgnores = [
70
- /\/@rstest\/core/,
71
- /rstest\/packages\/core\/dist/,
72
- /node_modules\/tinypool/,
73
- /node_modules\/chai/,
74
- /node_modules\/@vitest\/expect/,
75
- /node_modules\/@vitest\/snapshot/,
76
- /node:\w+/,
77
- /webpack\/runtime/,
78
- /webpack\\runtime/,
79
- '<anonymous>'
80
- ];
81
- async function parseErrorStacktrace({ stack, getSourcemap, fullStack }) {
82
- return Promise.all((0, stacktrace_parser__WEBPACK_IMPORTED_MODULE_2__.q)(stack).filter((frame)=>fullStack ? true : frame.file && !stackIgnores.some((entry)=>frame.file?.match(entry))).map(async (frame)=>{
83
- const sourcemap = getSourcemap(frame.file);
84
- if (sourcemap) {
85
- const traceMap = new _jridgewell_trace_mapping__WEBPACK_IMPORTED_MODULE_1__.YX(sourcemap);
86
- const { line, column, source, name } = (0, _jridgewell_trace_mapping__WEBPACK_IMPORTED_MODULE_1__.sP)(traceMap, {
87
- line: frame.lineNumber,
88
- column: frame.column
89
- });
90
- if (!source) return null;
91
- return {
92
- ...frame,
93
- file: source,
94
- lineNumber: line,
95
- name,
96
- column
97
- };
98
- }
99
- return frame;
100
- })).then((frames)=>frames.filter((frame)=>null !== frame));
101
- }
102
- }
103
- };