@rspack/test-tools 1.6.0-beta.0 → 1.6.0

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.
Files changed (118) hide show
  1. package/dist/case/builtin.d.ts +3 -2
  2. package/dist/case/builtin.js +1 -1
  3. package/dist/case/cache.d.ts +2 -2
  4. package/dist/case/cache.js +13 -9
  5. package/dist/case/common.d.ts +11 -10
  6. package/dist/case/common.js +49 -43
  7. package/dist/case/compiler.d.ts +9 -8
  8. package/dist/case/compiler.js +5 -6
  9. package/dist/case/config.d.ts +6 -5
  10. package/dist/case/config.js +4 -1
  11. package/dist/case/defaults.d.ts +5 -4
  12. package/dist/case/defaults.js +10 -10
  13. package/dist/case/diagnostic.js +5 -6
  14. package/dist/case/error.d.ts +5 -5
  15. package/dist/case/error.js +7 -8
  16. package/dist/case/esm-output.js +30 -9
  17. package/dist/case/example.js +2 -2
  18. package/dist/case/hash.d.ts +2 -2
  19. package/dist/case/hash.js +1 -1
  20. package/dist/case/hook.d.ts +4 -3
  21. package/dist/case/hook.js +3 -2
  22. package/dist/case/hot-step.d.ts +2 -2
  23. package/dist/case/hot-step.js +4 -9
  24. package/dist/case/hot.d.ts +5 -4
  25. package/dist/case/hot.js +37 -49
  26. package/dist/case/incremental.d.ts +2 -2
  27. package/dist/case/incremental.js +1 -20
  28. package/dist/case/index.d.ts +0 -1
  29. package/dist/case/index.js +1 -3
  30. package/dist/case/multi-compiler.d.ts +9 -8
  31. package/dist/case/multi-compiler.js +3 -4
  32. package/dist/case/normal.js +5 -2
  33. package/dist/case/runner.d.ts +5 -4
  34. package/dist/case/runner.js +16 -11
  35. package/dist/case/serial.d.ts +2 -2
  36. package/dist/case/serial.js +1 -1
  37. package/dist/case/stats-api.d.ts +6 -5
  38. package/dist/case/stats-api.js +5 -7
  39. package/dist/case/stats-output.d.ts +3 -2
  40. package/dist/case/stats-output.js +1 -1
  41. package/dist/case/treeshaking.js +1 -1
  42. package/dist/case/watch.d.ts +8 -6
  43. package/dist/case/watch.js +21 -19
  44. package/dist/compiler.d.ts +16 -17
  45. package/dist/compiler.js +116 -16
  46. package/dist/helper/hot-update/loader.d.ts +2 -1
  47. package/dist/helper/hot-update/loader.js +5 -30
  48. package/dist/helper/hot-update/plugin.js +10 -14
  49. package/dist/helper/index.d.ts +1 -0
  50. package/dist/helper/index.js +1 -0
  51. package/dist/helper/legacy/asModule.js +0 -2
  52. package/dist/helper/legacy/checkArrayExpectation.js +1 -1
  53. package/dist/helper/legacy/createLazyTestEnv.d.ts +1 -0
  54. package/dist/helper/legacy/createLazyTestEnv.js +4 -3
  55. package/dist/helper/legacy/supportsTextDecoder.d.ts +2 -0
  56. package/dist/helper/legacy/supportsTextDecoder.js +9 -0
  57. package/dist/helper/read-config-file.d.ts +3 -2
  58. package/dist/helper/read-config-file.js +12 -2
  59. package/dist/helper/setup-env.js +19 -2
  60. package/dist/helper/stringify-config.d.ts +2 -0
  61. package/dist/helper/stringify-config.js +43 -0
  62. package/dist/helper/util/expectWarningFactory.js +2 -4
  63. package/dist/index.d.ts +0 -1
  64. package/dist/index.js +0 -1
  65. package/dist/plugin/index.d.ts +0 -3
  66. package/dist/plugin/index.js +0 -3
  67. package/dist/runner/node/index.d.ts +13 -8
  68. package/dist/runner/node/index.js +88 -10
  69. package/dist/runner/web/index.d.ts +24 -10
  70. package/dist/runner/web/index.js +286 -18
  71. package/dist/test/context.d.ts +15 -16
  72. package/dist/test/context.js +44 -59
  73. package/dist/test/creator.d.ts +14 -14
  74. package/dist/test/creator.js +17 -12
  75. package/dist/test/debug.d.ts +15 -0
  76. package/dist/test/debug.js +205 -0
  77. package/dist/test/tester.d.ts +1 -0
  78. package/dist/test/tester.js +23 -4
  79. package/dist/type.d.ts +42 -55
  80. package/dist/type.js +1 -11
  81. package/jest.d.ts +2 -0
  82. package/package.json +10 -48
  83. package/dist/case/diff.d.ts +0 -19
  84. package/dist/case/diff.js +0 -274
  85. package/dist/compare/comparator.d.ts +0 -17
  86. package/dist/compare/comparator.js +0 -52
  87. package/dist/compare/compare.d.ts +0 -17
  88. package/dist/compare/compare.js +0 -178
  89. package/dist/compare/format-code.d.ts +0 -16
  90. package/dist/compare/format-code.js +0 -244
  91. package/dist/compare/index.d.ts +0 -5
  92. package/dist/compare/index.js +0 -21
  93. package/dist/compare/replace-module-argument.d.ts +0 -1
  94. package/dist/compare/replace-module-argument.js +0 -8
  95. package/dist/compare/replace-runtime-module-name.d.ts +0 -1
  96. package/dist/compare/replace-runtime-module-name.js +0 -71
  97. package/dist/helper/legacy/FakeDocument.d.ts +0 -54
  98. package/dist/helper/legacy/FakeDocument.js +0 -280
  99. package/dist/helper/legacy/update.d.ts +0 -2
  100. package/dist/helper/legacy/update.esm.d.ts +0 -1
  101. package/dist/helper/legacy/update.esm.js +0 -23
  102. package/dist/helper/legacy/update.js +0 -19
  103. package/dist/helper/legacy/walkCssTokens.d.ts +0 -40
  104. package/dist/helper/legacy/walkCssTokens.js +0 -761
  105. package/dist/plugin/rspack-diff-config-plugin.d.ts +0 -7
  106. package/dist/plugin/rspack-diff-config-plugin.js +0 -42
  107. package/dist/plugin/webpack-diff-config-plugin.d.ts +0 -7
  108. package/dist/plugin/webpack-diff-config-plugin.js +0 -41
  109. package/dist/plugin/webpack-module-placeholder-plugin.d.ts +0 -3
  110. package/dist/plugin/webpack-module-placeholder-plugin.js +0 -106
  111. package/dist/runner/web/fake.d.ts +0 -15
  112. package/dist/runner/web/fake.js +0 -216
  113. package/dist/runner/web/jsdom.d.ts +0 -24
  114. package/dist/runner/web/jsdom.js +0 -224
  115. package/template/diff.bundle.css +0 -1
  116. package/template/diff.bundle.js +0 -144
  117. package/template/diff.html +0 -14
  118. package/template/editor.worker.js +0 -1
@@ -18,8 +18,6 @@ module.exports = async (something, context, unlinked) => {
18
18
  if (unlinked)
19
19
  return m;
20
20
  await m.link(() => { });
21
- if (m.instantiate)
22
- m.instantiate();
23
21
  await m.evaluate();
24
22
  return m;
25
23
  };
@@ -1,6 +1,6 @@
1
1
  // @ts-nocheck
2
2
  "use strict";
3
- const fs = require("graceful-fs");
3
+ const fs = require("fs-extra");
4
4
  const path = require("node:path");
5
5
  const check = (expected, actual) => {
6
6
  if (expected instanceof RegExp) {
@@ -6,5 +6,6 @@ declare function _exports(globalTimeout?: number, nameSuffix?: string): {
6
6
  afterEach(...args: any[]): void;
7
7
  expect: jest.Expect;
8
8
  jest: typeof jest;
9
+ rstest: typeof jest;
9
10
  };
10
11
  export = _exports;
@@ -39,11 +39,10 @@ module.exports = (globalTimeout = 2000, nameSuffix = "") => {
39
39
  it("should run the exported tests", () => {
40
40
  runTests++;
41
41
  });
42
- afterAll(done => {
42
+ afterAll(() => {
43
43
  for (const dispose of disposables) {
44
44
  dispose();
45
45
  }
46
- done();
47
46
  });
48
47
  currentDescribeBlock = state.currentDescribeBlock;
49
48
  currentlyRunningTest = state.currentlyRunningTest;
@@ -111,6 +110,8 @@ module.exports = (globalTimeout = 2000, nameSuffix = "") => {
111
110
  });
112
111
  },
113
112
  expect,
114
- jest
113
+ jest,
114
+ // Compatible with rstest
115
+ rstest: global.rstest || global.jest
115
116
  };
116
117
  };
@@ -0,0 +1,2 @@
1
+ declare function _exports(): boolean;
2
+ export = _exports;
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ module.exports = function supportsTextDecoder() {
3
+ try {
4
+ return typeof TextDecoder !== "undefined";
5
+ }
6
+ catch (_err) {
7
+ return false;
8
+ }
9
+ };
@@ -1,2 +1,3 @@
1
- import type { ECompilerType, TCompilerOptions } from "../type";
2
- export declare function readConfigFile<T extends ECompilerType>(files: string[], functionApply?: (config: (TCompilerOptions<T> | ((...args: unknown[]) => TCompilerOptions<T>))[]) => TCompilerOptions<T>[]): TCompilerOptions<T>[];
1
+ import type { RspackOptions } from "@rspack/core";
2
+ import type { ITestContext } from "../type";
3
+ export declare function readConfigFile(files: string[], context: ITestContext, prevOption?: RspackOptions, functionApply?: (config: (RspackOptions | ((...args: unknown[]) => RspackOptions))[]) => RspackOptions[]): RspackOptions[];
@@ -5,9 +5,19 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.readConfigFile = readConfigFile;
7
7
  const fs_extra_1 = __importDefault(require("fs-extra"));
8
- function readConfigFile(files, functionApply) {
8
+ const debug_1 = require("../test/debug");
9
+ function readConfigFile(files, context, prevOption, functionApply) {
9
10
  const existsFile = files.find(i => fs_extra_1.default.existsSync(i));
10
- const fileConfig = existsFile ? require(existsFile) : {};
11
+ let fileConfig = existsFile ? require(existsFile) : {};
12
+ if (typeof fileConfig === "function") {
13
+ fileConfig = fileConfig({ config: prevOption }, { testPath: context.getDist(), tempPath: context.getTemp() });
14
+ }
11
15
  const configArr = Array.isArray(fileConfig) ? fileConfig : [fileConfig];
16
+ if (existsFile) {
17
+ context.setValue(debug_1.DEBUG_SCOPES.CompilerOptionsReadConfigFile, {
18
+ file: existsFile,
19
+ config: fileConfig
20
+ });
21
+ }
12
22
  return functionApply ? functionApply(configArr) : configArr;
13
23
  }
@@ -6,6 +6,22 @@ const path = require("node:path");
6
6
  if (process.env.RSPACK_BINDING_BUILDER_TESTING) {
7
7
  process.env.RSPACK_BINDING = path.resolve(__dirname, "../../node_modules/@rspack/binding-testing");
8
8
  }
9
+ if (process.env.RSTEST) {
10
+ global.printLogger ??= process.env.printLogger === "true";
11
+ global.__TEST_FIXTURES_PATH__ ??= process.env.__TEST_FIXTURES_PATH__;
12
+ global.updateSnapshot ??= process.env.updateSnapshot === "true";
13
+ global.testFilter ??= process.env.testFilter;
14
+ global.__TEST_PATH__ ??= process.env.__TEST_PATH__;
15
+ global.__TEST_DIST_PATH__ ??= process.env.__TEST_DIST_PATH__;
16
+ global.__ROOT_PATH__ ??= process.env.__ROOT_PATH__;
17
+ global.__RSPACK_PATH__ ??= process.env.__RSPACK_PATH__;
18
+ global.__RSPACK_TEST_TOOLS_PATH__ ??= process.env.__RSPACK_TEST_TOOLS_PATH__;
19
+ global.__DEBUG__ ??= process.env.DEBUG === "test";
20
+ }
21
+ else {
22
+ // Compatible with wasm tests (lazyTestEnv)
23
+ global.rstest = jest;
24
+ }
9
25
  if (process.env.ALTERNATIVE_SORT) {
10
26
  const oldSort = Array.prototype.sort;
11
27
  Array.prototype.sort = function (cmp) {
@@ -58,7 +74,8 @@ if (process.env.DEBUG_INFO) {
58
74
  }, timeout);
59
75
  }
60
76
  else {
61
- it(name, done => {
77
+ it(name, () => new Promise((resolve, reject) => {
78
+ const done = err => (err ? reject(err) : resolve());
62
79
  process.stdout.write(`START2 ${name}\n`);
63
80
  return fn(err => {
64
81
  if (err) {
@@ -69,7 +86,7 @@ if (process.env.DEBUG_INFO) {
69
86
  }
70
87
  return done(err);
71
88
  });
72
- }, timeout);
89
+ }), timeout);
73
90
  }
74
91
  };
75
92
  };
@@ -0,0 +1,2 @@
1
+ import type { RspackOptions } from "@rspack/core";
2
+ export default function stringifyConfig(config: RspackOptions, verbose?: boolean): string | undefined;
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = stringifyConfig;
4
+ const javascript_stringify_1 = require("javascript-stringify");
5
+ function stringifyConfig(config, verbose = false) {
6
+ return (0, javascript_stringify_1.stringify)(config, (value, indent, stringify) => {
7
+ // improve plugin output
8
+ if (value?.__pluginName) {
9
+ const prefix = `/* config.${value.__pluginType}('${value.__pluginName}') */\n`;
10
+ const constructorExpression = value.__pluginPath
11
+ ? // The path is stringified to ensure special characters are escaped
12
+ // (such as the backslashes in Windows-style paths).
13
+ `(require(${stringify(value.__pluginPath)}))`
14
+ : value.__pluginConstructorName;
15
+ if (constructorExpression) {
16
+ // get correct indentation for args by stringifying the args array and
17
+ // discarding the square brackets.
18
+ const args = stringify(value.__pluginArgs)?.slice(1, -1);
19
+ return `${prefix}new ${constructorExpression}(${args})`;
20
+ }
21
+ return (prefix +
22
+ stringify(value.__pluginArgs?.length ? { args: value.__pluginArgs } : {}));
23
+ }
24
+ // improve rule/use output
25
+ if (value?.__ruleNames) {
26
+ const ruleTypes = value.__ruleTypes;
27
+ const prefix = `/* config.module${value.__ruleNames
28
+ .map((r, index) => `.${ruleTypes ? ruleTypes[index] : "rule"}('${r}')`)
29
+ .join("")}${value.__useName ? `.use('${value.__useName}')` : ``} */\n`;
30
+ return prefix + stringify(value);
31
+ }
32
+ if (value?.__expression) {
33
+ return value.__expression;
34
+ }
35
+ // shorten long functions
36
+ if (typeof value === "function") {
37
+ if (!verbose && value.toString().length > 100) {
38
+ return `function () { /* omitted long function */ }`;
39
+ }
40
+ }
41
+ return stringify(value);
42
+ }, 2);
43
+ }
@@ -3,15 +3,13 @@
3
3
  module.exports = () => {
4
4
  const warnings = [];
5
5
  let oldWarn;
6
- beforeEach(done => {
6
+ beforeEach(() => {
7
7
  oldWarn = console.warn;
8
8
  console.warn = m => warnings.push(m);
9
- done();
10
9
  });
11
- afterEach(done => {
10
+ afterEach(() => {
12
11
  expectWarning();
13
12
  console.warn = oldWarn;
14
- done();
15
13
  });
16
14
  const expectWarning = (...regexp) => {
17
15
  expect(warnings).toEqual(regexp.map(r => expect.stringMatching(r)));
package/dist/index.d.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  export * from "./case";
2
- export * from "./compare";
3
2
  export * from "./helper";
4
3
  export * from "./plugin";
5
4
  export * from "./runner";
package/dist/index.js CHANGED
@@ -15,7 +15,6 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./case"), exports);
18
- __exportStar(require("./compare"), exports);
19
18
  __exportStar(require("./helper"), exports);
20
19
  __exportStar(require("./plugin"), exports);
21
20
  __exportStar(require("./runner"), exports);
@@ -1,4 +1 @@
1
1
  export * from "./lazy-compilation-test-plugin";
2
- export * from "./rspack-diff-config-plugin";
3
- export * from "./webpack-diff-config-plugin";
4
- export * from "./webpack-module-placeholder-plugin";
@@ -15,6 +15,3 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./lazy-compilation-test-plugin"), exports);
18
- __exportStar(require("./rspack-diff-config-plugin"), exports);
19
- __exportStar(require("./webpack-diff-config-plugin"), exports);
20
- __exportStar(require("./webpack-module-placeholder-plugin"), exports);
@@ -1,25 +1,29 @@
1
- import { type ECompilerType, type IGlobalContext, type IModuleScope, type ITestEnv, type ITestRunner, type TCompilerOptions, type TCompilerStatsCompilation, type TModuleObject, type TRunnerFile, type TRunnerRequirer, type TTestConfig } from "../../type";
1
+ import type { RspackOptions, StatsCompilation } from "@rspack/core";
2
+ import { type IGlobalContext, type IModuleScope, type ITestEnv, type ITestRunner, type TModuleObject, type TRunnerFile, type TRunnerRequirer, type TTestConfig } from "../../type";
2
3
  declare global {
3
4
  var printLogger: boolean;
4
5
  }
5
- export interface INodeRunnerOptions<T extends ECompilerType> {
6
+ export interface INodeRunnerOptions {
6
7
  env: ITestEnv;
7
- stats?: () => TCompilerStatsCompilation<T>;
8
+ stats?: () => StatsCompilation;
8
9
  name: string;
9
10
  runInNewContext?: boolean;
10
- testConfig: TTestConfig<T>;
11
+ testConfig: TTestConfig;
11
12
  source: string;
12
13
  dist: string;
13
- compilerOptions: TCompilerOptions<T>;
14
+ compilerOptions: RspackOptions;
14
15
  cachable?: boolean;
16
+ logs?: string[];
17
+ errors?: Error[];
15
18
  }
16
- export declare class NodeRunner<T extends ECompilerType = ECompilerType.Rspack> implements ITestRunner {
17
- protected _options: INodeRunnerOptions<T>;
19
+ export declare class NodeRunner implements ITestRunner {
20
+ protected _options: INodeRunnerOptions;
18
21
  protected requireCache: any;
19
22
  protected globalContext: IGlobalContext | null;
20
23
  protected baseModuleScope: IModuleScope | null;
21
24
  protected requirers: Map<string, TRunnerRequirer>;
22
- constructor(_options: INodeRunnerOptions<T>);
25
+ constructor(_options: INodeRunnerOptions);
26
+ protected log(message: string): void;
23
27
  run(file: string): Promise<unknown>;
24
28
  getRequire(): TRunnerRequirer;
25
29
  getGlobal(name: string): unknown;
@@ -35,3 +39,4 @@ export declare class NodeRunner<T extends ECompilerType = ECompilerType.Rspack>
35
39
  protected createCjsRequirer(): TRunnerRequirer;
36
40
  protected createEsmRequirer(): TRunnerRequirer;
37
41
  }
42
+ export declare const createLocatedError: (collectedErrors: Error[], offset: number) => (e: Error, file: TRunnerFile) => Error;
@@ -36,7 +36,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
36
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
37
37
  };
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.NodeRunner = void 0;
39
+ exports.createLocatedError = exports.NodeRunner = void 0;
40
40
  const node_fs_1 = __importDefault(require("node:fs"));
41
41
  const node_path_1 = __importDefault(require("node:path"));
42
42
  const node_url_1 = require("node:url");
@@ -45,6 +45,7 @@ const asModule_1 = __importDefault(require("../../helper/legacy/asModule"));
45
45
  const createFakeWorker_1 = __importDefault(require("../../helper/legacy/createFakeWorker"));
46
46
  const urlToRelativePath_1 = __importDefault(require("../../helper/legacy/urlToRelativePath"));
47
47
  const type_1 = require("../../type");
48
+ const EVAL_LOCATION_REGEX = /<anonymous>:(\d+)/;
48
49
  const isRelativePath = (p) => /^\.\.?\//.test(p);
49
50
  const getSubPath = (p) => {
50
51
  const lastSlash = p.lastIndexOf("/");
@@ -72,6 +73,9 @@ class NodeRunner {
72
73
  this.baseModuleScope = null;
73
74
  this.requirers = new Map();
74
75
  }
76
+ log(message) {
77
+ this._options.logs?.push(`[NodeRunner] ${message}`);
78
+ }
75
79
  run(file) {
76
80
  if (!this.globalContext) {
77
81
  this.globalContext = this.createGlobalContext();
@@ -81,7 +85,9 @@ class NodeRunner {
81
85
  this._options.testConfig.moduleScope(this.baseModuleScope, this._options.stats, this._options.compilerOptions);
82
86
  }
83
87
  this.createRunner();
84
- const res = this.getRequire()(this._options.dist, file.startsWith("./") || file.startsWith("https://test.cases/")
88
+ const res = this.getRequire()(node_path_1.default.isAbsolute(file) ? node_path_1.default.dirname(file) : this._options.dist, file.startsWith("./") ||
89
+ file.startsWith("https://test.cases/") ||
90
+ node_path_1.default.isAbsolute(file)
85
91
  ? file
86
92
  : `./${file}`);
87
93
  if (typeof res === "object" && "then" in res) {
@@ -91,7 +97,15 @@ class NodeRunner {
91
97
  }
92
98
  getRequire() {
93
99
  const entryRequire = this.requirers.get("entry");
94
- return (currentDirectory, modulePath, context = {}) => {
100
+ const runner = this;
101
+ return function (currentDirectory, modulePath, context = {}) {
102
+ const from = this?.from;
103
+ if (from) {
104
+ runner.log(`require: ${modulePath} from ${from}`);
105
+ }
106
+ else {
107
+ runner.log(`require: ${modulePath}`);
108
+ }
95
109
  const p = Array.isArray(modulePath)
96
110
  ? modulePath
97
111
  : modulePath.split("?")[0];
@@ -164,6 +178,7 @@ class NodeRunner {
164
178
  Symbol,
165
179
  Buffer,
166
180
  setImmediate,
181
+ self: this.globalContext,
167
182
  __MODE__: this._options.compilerOptions.mode,
168
183
  __SNAPSHOT__: node_path_1.default.join(this._options.source, "__snapshot__"),
169
184
  Worker: (0, createFakeWorker_1.default)(this._options.env, {
@@ -174,7 +189,10 @@ class NodeRunner {
174
189
  return baseModuleScope;
175
190
  }
176
191
  createModuleScope(requireFn, m, file) {
177
- const requirer = requireFn.bind(null, node_path_1.default.dirname(file.path));
192
+ const requirer = requireFn.bind({
193
+ from: file.path,
194
+ module: m
195
+ }, node_path_1.default.dirname(file.path));
178
196
  requirer.webpackTestSuiteRequire = true;
179
197
  return {
180
198
  ...this.baseModuleScope,
@@ -243,6 +261,7 @@ class NodeRunner {
243
261
  this.requirers.set("json", this.createJsonRequirer());
244
262
  this.requirers.set("entry", (currentDirectory, modulePath, context) => {
245
263
  const file = this.getFile(modulePath, currentDirectory);
264
+ this.log(`entry: ${modulePath} -> ${file?.path}`);
246
265
  if (!file) {
247
266
  return this.requirers.get("miss")(currentDirectory, modulePath);
248
267
  }
@@ -267,11 +286,14 @@ class NodeRunner {
267
286
  }
268
287
  createMissRequirer() {
269
288
  return (currentDirectory, modulePath, context = {}) => {
289
+ this.log(`missing: ${modulePath}`);
270
290
  const modulePathStr = modulePath;
271
291
  const modules = this._options.testConfig.modules;
272
292
  if (modules && modulePathStr in modules) {
293
+ this.log(`mock module: ${modulePathStr}`);
273
294
  return modules[modulePathStr];
274
295
  }
296
+ this.log(`native require: ${modulePathStr}`);
275
297
  return require(modulePathStr.startsWith("node:")
276
298
  ? modulePathStr.slice(5)
277
299
  : modulePathStr);
@@ -283,6 +305,7 @@ class NodeRunner {
283
305
  throw new Error("Array module path is not supported in hot cases");
284
306
  }
285
307
  const file = context.file || this.getFile(modulePath, currentDirectory);
308
+ this.log(`json: ${modulePath} -> ${file?.path}`);
286
309
  if (!file) {
287
310
  return this.requirers.get("miss")(currentDirectory, modulePath);
288
311
  }
@@ -295,10 +318,12 @@ class NodeRunner {
295
318
  return require("@rspack/test-tools");
296
319
  }
297
320
  const file = context.file || this.getFile(modulePath, currentDirectory);
321
+ this.log(`cjs: ${modulePath} -> ${file?.path}`);
298
322
  if (!file) {
299
323
  return this.requirers.get("miss")(currentDirectory, modulePath);
300
324
  }
301
325
  if (file.path in this.requireCache) {
326
+ this.log(`cjs cache hit: ${file.path}`);
302
327
  return this.requireCache[file.path].exports;
303
328
  }
304
329
  const m = {
@@ -307,7 +332,7 @@ class NodeRunner {
307
332
  };
308
333
  this.requireCache[file.path] = m;
309
334
  if (!this._options.runInNewContext) {
310
- file.content = `Object.assign(global, _globalAssign);\n ${file.content}`;
335
+ file.content = `Object.assign(global, _globalAssign);${file.content}`;
311
336
  }
312
337
  const currentModuleScope = this.createModuleScope(this.getRequire(), m, file);
313
338
  if (this._options.testConfig.moduleScope) {
@@ -322,19 +347,39 @@ class NodeRunner {
322
347
  currentModuleScope.__STATS_I__ = statsIndex;
323
348
  }
324
349
  }
350
+ const createNodeLocatedError = (0, exports.createLocatedError)(this._options.errors || [], 2);
351
+ const originIt = currentModuleScope.it;
352
+ currentModuleScope.it = (description, fn) => {
353
+ originIt(description, async () => {
354
+ try {
355
+ await fn();
356
+ }
357
+ catch (err) {
358
+ throw createNodeLocatedError(err, file);
359
+ }
360
+ });
361
+ };
362
+ currentModuleScope.__CREATE_LOCATED_ERROR__ = createNodeLocatedError;
363
+ currentModuleScope.__FILE__ = file;
325
364
  const args = Object.keys(currentModuleScope);
326
365
  const argValues = args.map(arg => currentModuleScope[arg]);
327
366
  const code = `(function(${args.join(", ")}) {
328
- ${file.content}
367
+ try {
368
+ ${file.content}
369
+ } catch(err) {
370
+ throw __CREATE_LOCATED_ERROR__(err, __FILE__);
371
+ }
329
372
  })`;
330
373
  this.preExecute(code, file);
374
+ this.log(`run mode: ${this._options.runInNewContext ? "new context" : "this context"}`);
331
375
  const fn = this._options.runInNewContext
332
- ? node_vm_1.default.runInNewContext(code, this.globalContext, file.path)
333
- : node_vm_1.default.runInThisContext(code, file.path);
376
+ ? node_vm_1.default.runInNewContext(code, this.globalContext)
377
+ : node_vm_1.default.runInThisContext(code);
334
378
  fn.call(this._options.testConfig.nonEsmThis
335
379
  ? this._options.testConfig.nonEsmThis(modulePath)
336
380
  : m.exports, ...argValues);
337
381
  this.postExecute(m, file);
382
+ this.log(`end cjs: ${modulePath}`);
338
383
  return m.exports;
339
384
  };
340
385
  }
@@ -350,12 +395,19 @@ class NodeRunner {
350
395
  }
351
396
  const _require = this.getRequire();
352
397
  const file = context.file || this.getFile(modulePath, currentDirectory);
398
+ this.log(`esm: ${modulePath} -> ${file?.path}`);
353
399
  if (!file) {
354
400
  return this.requirers.get("miss")(currentDirectory, modulePath);
355
401
  }
356
402
  if (file.content.includes("__STATS__")) {
357
403
  esmContext.__STATS__ = this._options.stats?.();
358
404
  }
405
+ if (file.content.includes("__STATS_I__")) {
406
+ const statsIndex = this._options.stats?.()?.__index__;
407
+ if (typeof statsIndex === "number") {
408
+ esmContext.__STATS_I__ = statsIndex;
409
+ }
410
+ }
359
411
  let esm = esmCache.get(file.path);
360
412
  if (!esm) {
361
413
  esm = new node_vm_1.SourceTextModule(file.content, {
@@ -369,6 +421,7 @@ class NodeRunner {
369
421
  meta.filename = file.path;
370
422
  },
371
423
  importModuleDynamically: async (specifier, module) => {
424
+ this.log(`import: ${specifier} from ${file?.path}`);
372
425
  const result = await _require(node_path_1.default.dirname(file.path), specifier, {
373
426
  esmMode: type_1.EEsmMode.Evaluated
374
427
  });
@@ -389,16 +442,41 @@ class NodeRunner {
389
442
  }), referencingModule.context, true);
390
443
  });
391
444
  }
392
- if (esm.instantiate)
393
- esm.instantiate();
394
445
  await esm.evaluate();
395
446
  if (context.esmMode === type_1.EEsmMode.Evaluated) {
396
447
  return esm;
397
448
  }
398
449
  const ns = esm.namespace;
450
+ this.log(`end esm: ${modulePath}`);
399
451
  return ns.default && ns.default instanceof Promise ? ns.default : ns;
400
452
  })();
401
453
  };
402
454
  }
403
455
  }
404
456
  exports.NodeRunner = NodeRunner;
457
+ const createLocatedError = (collectedErrors, offset) => {
458
+ return (e, file) => {
459
+ const match = (e.stack || e.message).match(EVAL_LOCATION_REGEX);
460
+ if (match) {
461
+ const [, line] = match;
462
+ const realLine = Number(line) - offset;
463
+ const codeLines = file.content.split("\n");
464
+ const lineContents = [
465
+ ...codeLines
466
+ .slice(Math.max(0, realLine - 3), Math.max(0, realLine - 1))
467
+ .map(line => `│ ${line}`),
468
+ `│> ${codeLines[realLine - 1]}`,
469
+ ...codeLines.slice(realLine, realLine + 2).map(line => `│ ${line}`)
470
+ ];
471
+ const message = `Error in JSDOM when running file '${file.path}' at line ${realLine}: ${e.message}\n${lineContents.join("\n")}`;
472
+ const finalError = new Error(message);
473
+ finalError.stack = undefined;
474
+ collectedErrors.push(finalError);
475
+ return finalError;
476
+ }
477
+ else {
478
+ return e;
479
+ }
480
+ };
481
+ };
482
+ exports.createLocatedError = createLocatedError;
@@ -1,14 +1,28 @@
1
- import { type ECompilerType, EDocumentType, type ITestRunner } from "../../type";
2
- import type { INodeRunnerOptions, NodeRunner } from "../node";
3
- export interface IWebRunnerOptions<T extends ECompilerType = ECompilerType.Rspack> extends INodeRunnerOptions<T> {
4
- dom: EDocumentType;
1
+ import type { TRunnerFile, TRunnerRequirer } from "../../type";
2
+ import { type INodeRunnerOptions, NodeRunner } from "../node";
3
+ export interface IWebRunnerOptions extends INodeRunnerOptions {
4
+ location: string;
5
5
  }
6
- export declare class WebRunner<T extends ECompilerType = ECompilerType.Rspack> implements ITestRunner {
7
- protected _webOptions: IWebRunnerOptions<T>;
8
- protected originMethods: Partial<NodeRunner<T>>;
9
- private implement;
10
- constructor(_webOptions: IWebRunnerOptions<T>);
6
+ export declare class WebRunner extends NodeRunner {
7
+ protected _webOptions: IWebRunnerOptions;
8
+ private dom;
9
+ constructor(_webOptions: IWebRunnerOptions);
11
10
  run(file: string): Promise<unknown>;
12
- getRequire(): import("../../type").TRunnerRequirer;
13
11
  getGlobal(name: string): unknown;
12
+ protected log(message: string): void;
13
+ protected createResourceLoader(): {
14
+ fetch(url: string, _: {
15
+ element: HTMLScriptElement;
16
+ }): any;
17
+ };
18
+ private urlToPath;
19
+ protected createBaseModuleScope(): import("../../type").IModuleScope;
20
+ protected getModuleContent(file: TRunnerFile): [
21
+ {
22
+ exports: Record<string, unknown>;
23
+ },
24
+ string
25
+ ];
26
+ protected createJSDOMRequirer(): TRunnerRequirer;
27
+ protected createRunner(): void;
14
28
  }