@rspack-canary/test-tools 1.5.4-canary-55493775-20250914174633 → 1.5.5-canary-f4d631e6-20250915072424

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 (42) hide show
  1. package/dist/case/config.js +2 -2
  2. package/dist/case/serial.js +2 -2
  3. package/dist/helper/legacy/FakeDocument.js +6 -4
  4. package/dist/helper/legacy/createFakeWorker.d.ts +1 -1
  5. package/dist/helper/legacy/createFakeWorker.js +44 -20
  6. package/dist/helper/legacy/expectSource.d.ts +10 -0
  7. package/dist/helper/legacy/expectSource.js +23 -0
  8. package/dist/helper/legacy/findOutputFiles.d.ts +6 -0
  9. package/dist/helper/legacy/findOutputFiles.js +14 -0
  10. package/dist/helper/legacy/regexEscape.d.ts +2 -0
  11. package/dist/helper/legacy/regexEscape.js +5 -0
  12. package/dist/helper/legacy/supportsBlob.d.ts +2 -0
  13. package/dist/helper/legacy/supportsBlob.js +10 -0
  14. package/dist/helper/legacy/supportsOptionalChaining.d.ts +2 -0
  15. package/dist/helper/legacy/supportsOptionalChaining.js +11 -0
  16. package/dist/helper/legacy/supportsResponse.d.ts +2 -0
  17. package/dist/helper/legacy/supportsResponse.js +10 -0
  18. package/dist/helper/legacy/supportsWebAssembly.d.ts +2 -0
  19. package/dist/helper/legacy/supportsWebAssembly.js +10 -0
  20. package/dist/helper/legacy/supportsWorker.d.ts +2 -0
  21. package/dist/helper/legacy/supportsWorker.js +17 -0
  22. package/dist/helper/legacy/urlToRelativePath.js +5 -2
  23. package/dist/processor/basic.js +5 -5
  24. package/dist/processor/config.js +5 -0
  25. package/dist/processor/hot.d.ts +1 -1
  26. package/dist/processor/hot.js +6 -2
  27. package/dist/processor/watch.js +1 -1
  28. package/dist/runner/cache.js +1 -1
  29. package/dist/runner/hot-step.js +1 -1
  30. package/dist/runner/hot.js +1 -1
  31. package/dist/runner/multiple.js +16 -2
  32. package/dist/runner/runner/basic.js +13 -11
  33. package/dist/runner/runner/cjs.d.ts +2 -0
  34. package/dist/runner/runner/cjs.js +37 -11
  35. package/dist/runner/runner/esm.js +3 -0
  36. package/dist/runner/runner/web/fake.d.ts +0 -1
  37. package/dist/runner/runner/web/fake.js +0 -12
  38. package/dist/runner/runner/web/jsdom.d.ts +0 -1
  39. package/dist/runner/runner/web/jsdom.js +1 -2
  40. package/dist/test/creator.js +1 -1
  41. package/dist/type.d.ts +4 -4
  42. package/package.json +4 -4
@@ -10,11 +10,11 @@ const creator = new creator_1.BasicCaseCreator({
10
10
  describe: false,
11
11
  testConfig: testConfig => {
12
12
  const oldModuleScope = testConfig.moduleScope;
13
- testConfig.moduleScope = (ms, stats) => {
13
+ testConfig.moduleScope = (ms, stats, compilerOptions) => {
14
14
  let res = ms;
15
15
  // TODO: modify runner module scope based on stats here
16
16
  if (typeof oldModuleScope === "function") {
17
- res = oldModuleScope(ms, stats);
17
+ res = oldModuleScope(ms, stats, compilerOptions);
18
18
  }
19
19
  return res;
20
20
  };
@@ -10,11 +10,11 @@ const creator = new creator_1.BasicCaseCreator({
10
10
  describe: false,
11
11
  testConfig: testConfig => {
12
12
  const oldModuleScope = testConfig.moduleScope;
13
- testConfig.moduleScope = (ms, stats) => {
13
+ testConfig.moduleScope = (ms, stats, compilerOptions) => {
14
14
  let res = ms;
15
15
  // TODO: modify runner module scope based on stats here
16
16
  if (typeof oldModuleScope === "function") {
17
- res = oldModuleScope(ms, stats);
17
+ res = oldModuleScope(ms, stats, compilerOptions);
18
18
  }
19
19
  return res;
20
20
  };
@@ -223,12 +223,15 @@ class FakeSheet {
223
223
  currentRule[property] = value;
224
224
  }
225
225
  };
226
- const filepath = /file:\/\//.test(this._element.href)
227
- ? new URL(this._element.href)
226
+ let filepath = /file:\/\//.test(this._element.href)
227
+ ? new URL(this._element.href).pathname
228
228
  : path.resolve(this._basePath, this._element.href
229
229
  .replace(/^https:\/\/test\.cases\/path\//, "")
230
230
  .replace(/^https:\/\/example\.com\/public\/path\//, "")
231
231
  .replace(/^https:\/\/example\.com\//, ""));
232
+ if (require("os").platform() === "win32" && filepath.startsWith("/")) {
233
+ filepath = filepath.slice(1);
234
+ }
232
235
  let css = fs.readFileSync(filepath.replace(/\?hmr=\d*/, ""), "utf-8");
233
236
  css = css.replace(/@import url\("([^"]+)"\);/g, (match, url) => {
234
237
  if (!/^https:\/\/test\.cases\/path\//.test(url)) {
@@ -239,8 +242,7 @@ class FakeSheet {
239
242
  }
240
243
  return fs.readFileSync(path.resolve(this._basePath, url.replace(/^https:\/\/test\.cases\/path\//, "")), "utf-8");
241
244
  })
242
- .replace(/\/\*[\s\S]*?\*\//g, '')
243
- .replace("//", "");
245
+ .replace(/\/\*[\s\S]*?\*\//g, '');
244
246
  walkCssTokens(css, {
245
247
  isSelector() {
246
248
  return selector === undefined;
@@ -1,7 +1,7 @@
1
1
  declare function _exports(env: any, { outputDirectory }: {
2
2
  outputDirectory: any;
3
3
  }): {
4
- new (url: any, options?: {}): {
4
+ new (resource: any, options?: {}): {
5
5
  url: any;
6
6
  worker: import("worker_threads").Worker;
7
7
  _onmessage: ((data: any) => void) | undefined;
@@ -1,28 +1,38 @@
1
- "use strict";
2
1
  // @ts-nocheck
3
- const path = require("node:path");
2
+ "use strict";
3
+ const path = require("path");
4
4
  module.exports = (env, { outputDirectory }) => class Worker {
5
- constructor(url, options = {}) {
6
- env.expect(url).toBeInstanceOf(URL);
7
- env.expect(url.origin).toBe("https://test.cases");
8
- env.expect(url.pathname.startsWith("/path/")).toBe(true);
9
- this.url = url;
10
- const file = url.pathname.slice(6);
5
+ constructor(resource, options = {}) {
6
+ const isFileURL = /^file:/i.test(resource);
7
+ const isBlobURL = /^blob:/i.test(resource);
8
+ if (!isFileURL && !isBlobURL) {
9
+ env.expect(resource.origin).toBe("https://test.cases");
10
+ env.expect(resource.pathname.startsWith("/path/")).toBe(true);
11
+ }
12
+ this.url = resource;
13
+ const file = isFileURL
14
+ ? resource
15
+ : path.resolve(outputDirectory, isBlobURL
16
+ ? options.originalURL.pathname.slice(6)
17
+ : resource.pathname.slice(6));
11
18
  const workerBootstrap = `
12
19
  const { parentPort } = require("worker_threads");
13
- const { URL } = require("url");
20
+ const { URL, fileURLToPath } = require("url");
14
21
  const path = require("path");
15
22
  const fs = require("fs");
16
23
  global.self = global;
17
24
  self.URL = URL;
18
- self.location = new URL(${JSON.stringify(url.toString())});
25
+ self.location = new URL(${JSON.stringify(isBlobURL
26
+ ? resource.toString().replace("nodedata:", "https://test.cases/path/")
27
+ : resource.toString())});
19
28
  const urlToPath = url => {
20
- if(url.startsWith("https://test.cases/path/")) url = url.slice(24);
29
+ if (/^file:/i.test(url)) return fileURLToPath(url);
30
+ if (url.startsWith("https://test.cases/path/")) url = url.slice(24);
21
31
  return path.resolve(${JSON.stringify(outputDirectory)}, \`./\${url}\`);
22
32
  };
23
33
  self.importScripts = url => {
24
34
  ${options.type === "module"
25
- ? `throw new Error("importScripts is not supported in module workers")`
35
+ ? 'throw new Error("importScripts is not supported in module workers")'
26
36
  : "require(urlToPath(url))"};
27
37
  };
28
38
  self.fetch = async url => {
@@ -33,8 +43,10 @@ self.fetch = async url => {
33
43
  )
34
44
  );
35
45
  return {
46
+ headers: { get(name) { } },
36
47
  status: 200,
37
48
  ok: true,
49
+ arrayBuffer() { return buffer; },
38
50
  json: async () => JSON.parse(buffer.toString("utf-8"))
39
51
  };
40
52
  } catch(err) {
@@ -47,25 +59,37 @@ self.fetch = async url => {
47
59
  throw err;
48
60
  }
49
61
  };
50
- parentPort.on("message", data => {
51
- if(self.onmessage) self.onmessage({
52
- data
53
- });
54
- });
62
+
55
63
  self.postMessage = data => {
56
64
  parentPort.postMessage(data);
57
65
  };
58
- require(${JSON.stringify(path.resolve(outputDirectory, file))});
66
+ if (${options.type === "module"}) {
67
+ import(${JSON.stringify(file)}).then(() => {
68
+ parentPort.on("message", data => {
69
+ if(self.onmessage) self.onmessage({
70
+ data
71
+ });
72
+ });
73
+ });
74
+ } else {
75
+ parentPort.on("message", data => {
76
+ if(self.onmessage) self.onmessage({
77
+ data
78
+ });
79
+ });
80
+ require(${JSON.stringify(file)});
81
+ }
59
82
  `;
60
- this.worker = new (require("node:worker_threads").Worker)(workerBootstrap, {
83
+ this.worker = new (require("worker_threads").Worker)(workerBootstrap, {
61
84
  eval: true
62
85
  });
63
86
  this._onmessage = undefined;
64
87
  }
88
+ // eslint-disable-next-line accessor-pairs
65
89
  set onmessage(value) {
66
90
  if (this._onmessage)
67
91
  this.worker.off("message", this._onmessage);
68
- this.worker.on("message", (this._onmessage = data => {
92
+ this.worker.on("message", (this._onmessage = (data) => {
69
93
  value({
70
94
  data
71
95
  });
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @param {string} source value
3
+ * @param {string} str string for searching
4
+ */
5
+ export function expectSourceToContain(source: string, str: string): void;
6
+ /**
7
+ * @param {string} source value
8
+ * @param {RegExp} regexStr regexp
9
+ */
10
+ export function expectSourceToMatch(source: string, regexStr: RegExp): void;
@@ -0,0 +1,23 @@
1
+ // @ts-nocheck
2
+ "use strict";
3
+ const regexEscape = require("./regexEscape");
4
+ // These expect* methods are necessary because 'source' contains the code for this test file, which will always contain the string
5
+ // being tested for, so we have to use the "DO NOT MATCH BELOW..." technique to exclude the actual testing code from the test.
6
+ // Place your jest 'expect' calls below a line containing the DO NOT MATCH BELOW... string constructed below. See other tests for examples.
7
+ // Break up the match string so we don't match it in these expect* functions either.
8
+ const doNotMatch = ["DO", "NOT", "MATCH", "BELOW", "THIS", "LINE"].join(" ");
9
+ /**
10
+ * @param {string} source value
11
+ * @param {string} str string for searching
12
+ */
13
+ function expectSourceToContain(source, str) {
14
+ expect(source).toMatch(new RegExp(`${regexEscape(str)}.*${doNotMatch}`, "s"));
15
+ }
16
+ /**
17
+ * @param {string} source value
18
+ * @param {RegExp} regexStr regexp
19
+ */
20
+ function expectSourceToMatch(source, regexStr) {
21
+ expect(source).toMatch(new RegExp(`${regexStr}.*${doNotMatch}`, "s"));
22
+ }
23
+ module.exports = { expectSourceToContain, expectSourceToMatch };
@@ -0,0 +1,6 @@
1
+ declare function _exports(options: {
2
+ output: {
3
+ path: string;
4
+ };
5
+ }, regexp: RegExp, subpath?: string | undefined): string[];
6
+ export = _exports;
@@ -0,0 +1,14 @@
1
+ // @ts-nocheck
2
+ "use strict";
3
+ const fs = require("fs");
4
+ const path = require("path");
5
+ /**
6
+ * @param {{output: {path: string}}} options options
7
+ * @param {RegExp} regexp regexp
8
+ * @param {string=} subpath path in output directory
9
+ * @returns {string[]} files
10
+ */
11
+ module.exports = function findOutputFiles(options, regexp, subpath) {
12
+ const files = fs.readdirSync(subpath ? path.join(options.output.path, subpath) : options.output.path);
13
+ return files.filter(file => regexp.test(file));
14
+ };
@@ -0,0 +1,2 @@
1
+ declare function _exports(string: any): any;
2
+ export = _exports;
@@ -0,0 +1,5 @@
1
+ // @ts-nocheck
2
+ "use strict";
3
+ module.exports = function regexEscape(string) {
4
+ return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string
5
+ };
@@ -0,0 +1,2 @@
1
+ declare function _exports(): boolean;
2
+ export = _exports;
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ // @ts-nocheck
3
+ module.exports = function supportsBlob() {
4
+ try {
5
+ return typeof Blob !== "undefined";
6
+ }
7
+ catch (_err) {
8
+ return false;
9
+ }
10
+ };
@@ -0,0 +1,2 @@
1
+ declare function _exports(): any;
2
+ export = _exports;
@@ -0,0 +1,11 @@
1
+ // @ts-nocheck
2
+ "use strict";
3
+ module.exports = function supportsOptionalChaining() {
4
+ try {
5
+ const f = eval("(function f() { return ({a: true}) ?.a })");
6
+ return f();
7
+ }
8
+ catch (_err) {
9
+ return false;
10
+ }
11
+ };
@@ -0,0 +1,2 @@
1
+ declare function _exports(): boolean;
2
+ export = _exports;
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ // @ts-nocheck
3
+ module.exports = function supportsResponse() {
4
+ try {
5
+ return typeof Response !== "undefined";
6
+ }
7
+ catch (_err) {
8
+ return false;
9
+ }
10
+ };
@@ -0,0 +1,2 @@
1
+ declare function _exports(): boolean;
2
+ export = _exports;
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ // @ts-nocheck
3
+ module.exports = function supportsWebAssembly() {
4
+ try {
5
+ return typeof WebAssembly !== "undefined";
6
+ }
7
+ catch (e) {
8
+ return false;
9
+ }
10
+ };
@@ -0,0 +1,2 @@
1
+ declare function _exports(): boolean;
2
+ export = _exports;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ // @ts-nocheck
3
+ const nodeVersion = process.versions.node.split(".").map(Number);
4
+ module.exports = function supportsWorker() {
5
+ // Verify that in the current node version new Worker() accepts URL as the first parameter:
6
+ // https://nodejs.org/api/worker_threads.html#worker_threads_new_worker_filename_options
7
+ if (nodeVersion[0] >= 14) {
8
+ return true;
9
+ }
10
+ else if (nodeVersion[0] === 13 && nodeVersion[1] >= 12) {
11
+ return true;
12
+ }
13
+ else if (nodeVersion[0] === 12 && nodeVersion[1] >= 17) {
14
+ return true;
15
+ }
16
+ return false;
17
+ };
@@ -1,7 +1,10 @@
1
1
  "use strict";
2
2
  // @ts-nocheck
3
+ const URL = require("url").URL;
3
4
  module.exports = function urlToRelativePath(url) {
4
- if (url.startsWith("https://test.cases/path/"))
5
- url = url.slice(24);
5
+ if (url.startsWith("https://") || url.startsWith("file://")) {
6
+ const urlObj = new URL(url);
7
+ return `./${urlObj.pathname.split("/").pop()}`;
8
+ }
6
9
  return `./${url}`;
7
10
  };
@@ -38,15 +38,15 @@ class BasicProcessor {
38
38
  if (!this._options.runable)
39
39
  return;
40
40
  const testConfig = context.getTestConfig();
41
- if (testConfig.noTest)
41
+ if (testConfig.noTests)
42
42
  return;
43
43
  if (testConfig.documentType) {
44
44
  context.setValue(this._options.name, "documentType", testConfig.documentType);
45
45
  }
46
+ const compiler = this.getCompiler(context);
46
47
  if (typeof testConfig.beforeExecute === "function") {
47
- testConfig.beforeExecute();
48
+ testConfig.beforeExecute(compiler.getOptions());
48
49
  }
49
- const compiler = this.getCompiler(context);
50
50
  let bundles;
51
51
  if (testConfig.bundlePath) {
52
52
  bundles = testConfig.bundlePath;
@@ -83,12 +83,12 @@ class BasicProcessor {
83
83
  const results = context.getValue(this._options.name, "modules") || [];
84
84
  await Promise.all(results);
85
85
  if (typeof testConfig.afterExecute === "function") {
86
- testConfig.afterExecute();
86
+ testConfig.afterExecute(compiler.getOptions());
87
87
  }
88
88
  }
89
89
  async check(env, context) {
90
90
  const testConfig = context.getTestConfig();
91
- if (testConfig.noTest)
91
+ if (testConfig.noTests)
92
92
  return;
93
93
  const errors = (context.getError(this._options.name) || []).map(e => ({
94
94
  message: e.message,
@@ -66,11 +66,16 @@ class ConfigProcessor extends multi_1.MultiTaskProcessor {
66
66
  if (!options.entry) {
67
67
  options.entry = "./index.js";
68
68
  }
69
+ if (options.amd === undefined) {
70
+ options.amd = {};
71
+ }
69
72
  if (!options.output?.filename) {
70
73
  const outputModule = options.experiments?.outputModule;
71
74
  options.output ??= {};
72
75
  options.output.filename = `bundle${index}${outputModule ? ".mjs" : ".js"}`;
73
76
  }
77
+ if (options.cache === undefined)
78
+ options.cache = false;
74
79
  if (!global.printLogger) {
75
80
  options.infrastructureLogging = {
76
81
  level: "error"
@@ -10,7 +10,7 @@ export declare class HotProcessor<T extends ECompilerType> extends BasicProcesso
10
10
  protected runner: ITestRunner | null;
11
11
  constructor(_hotOptions: IHotProcessorOptions<T>);
12
12
  run(env: ITestEnv, context: ITestContext): Promise<void>;
13
- static findBundle<T extends ECompilerType>(this: HotProcessor<T>, context: ITestContext): string[];
13
+ static findBundle<T extends ECompilerType>(this: HotProcessor<T>, context: ITestContext): string | string[];
14
14
  afterAll(context: ITestContext): Promise<void>;
15
15
  static defaultOptions<T extends ECompilerType>(this: HotProcessor<T>, context: ITestContext): TCompilerOptions<T>;
16
16
  static overrideOptions<T extends ECompilerType>(this: HotProcessor<T>, context: ITestContext, options: TCompilerOptions<T>): void;
@@ -34,11 +34,15 @@ class HotProcessor extends basic_1.BasicProcessor {
34
34
  await super.run(env, context);
35
35
  }
36
36
  static findBundle(context) {
37
- const files = [];
38
- const prefiles = [];
39
37
  const compiler = context.getCompiler(this._hotOptions.name);
40
38
  if (!compiler)
41
39
  throw new Error("Compiler should exists when find bundle");
40
+ const testConfig = context.getTestConfig();
41
+ if (typeof testConfig.findBundle === "function") {
42
+ return testConfig.findBundle(this.updateOptions.updateIndex, compiler.getOptions());
43
+ }
44
+ const files = [];
45
+ const prefiles = [];
42
46
  const stats = compiler.getStats();
43
47
  if (!stats)
44
48
  throw new Error("Stats should exists when find bundle");
@@ -57,7 +57,7 @@ class WatchProcessor extends multi_1.MultiTaskProcessor {
57
57
  }
58
58
  async check(env, context) {
59
59
  const testConfig = context.getTestConfig();
60
- if (testConfig.noTest)
60
+ if (testConfig.noTests)
61
61
  return;
62
62
  const errors = (context.getError(this._options.name) || []).map(e => ({
63
63
  message: e.message,
@@ -30,7 +30,7 @@ class CacheRunnerFactory extends basic_1.BasicRunnerFactory {
30
30
  ...testConfig,
31
31
  moduleScope(ms, stats) {
32
32
  const moduleScope = typeof testConfig.moduleScope === "function"
33
- ? testConfig.moduleScope(ms, stats)
33
+ ? testConfig.moduleScope(ms, stats, compilerOptions)
34
34
  : ms;
35
35
  moduleScope.COMPILER_INDEX = compilerIndex;
36
36
  moduleScope.NEXT_HMR = nextHmr;
@@ -69,7 +69,7 @@ class HotStepRunnerFactory extends hot_1.HotRunnerFactory {
69
69
  moduleScope(ms, stats) {
70
70
  const moduleScope = ms;
71
71
  if (typeof testConfig.moduleScope === "function") {
72
- testConfig.moduleScope(moduleScope, stats);
72
+ testConfig.moduleScope(moduleScope, stats, compilerOptions);
73
73
  }
74
74
  moduleScope.NEXT = next;
75
75
  moduleScope.NEXT_HMR = nextHMR;
@@ -66,7 +66,7 @@ class HotRunnerFactory extends basic_1.BasicRunnerFactory {
66
66
  moduleScope(ms, stats) {
67
67
  const moduleScope = ms;
68
68
  if (typeof testConfig.moduleScope === "function") {
69
- testConfig.moduleScope(moduleScope, stats);
69
+ testConfig.moduleScope(moduleScope, stats, compilerOptions);
70
70
  }
71
71
  moduleScope.NEXT = next;
72
72
  moduleScope.NEXT_HMR = nextHMR;
@@ -13,11 +13,25 @@ class MultipleRunnerFactory extends basic_1.BasicRunnerFactory {
13
13
  return `${this.name}-${index}[${seq}]`;
14
14
  }
15
15
  createRunner(file, stats, compilerOptions, env) {
16
- const multiCompilerOptions = this.context.getValue(this.name, "multiCompilerOptions") || [];
17
16
  const { getIndex, flagIndex } = this.getFileIndexHandler(file);
17
+ const key = this.getRunnerKey(file);
18
+ const exists = this.context.getRunner(key);
19
+ if (exists) {
20
+ flagIndex();
21
+ return exists;
22
+ }
23
+ const multiCompilerOptions = this.context.getValue(this.name, "multiCompilerOptions") || [];
18
24
  const [index] = getIndex();
19
- const runner = super.createRunner(file, () => stats().children[index], multiCompilerOptions[index], env);
25
+ const runner = super.createRunner(file, () => {
26
+ const s = stats();
27
+ if (s.children?.length && s.children.length > 1) {
28
+ s.__index__ = index;
29
+ return s;
30
+ }
31
+ return s.children[index];
32
+ }, multiCompilerOptions[index], env);
20
33
  flagIndex();
34
+ this.context.setRunner(key, runner);
21
35
  return runner;
22
36
  }
23
37
  getFileIndexHandler(file) {
@@ -39,10 +39,12 @@ class BasicRunner {
39
39
  }
40
40
  this.baseModuleScope = this.createBaseModuleScope();
41
41
  if (typeof this._options.testConfig.moduleScope === "function") {
42
- this._options.testConfig.moduleScope(this.baseModuleScope, this._options.stats);
42
+ this._options.testConfig.moduleScope(this.baseModuleScope, this._options.stats, this._options.compilerOptions);
43
43
  }
44
44
  this.createRunner();
45
- const res = this.getRequire()(this._options.dist, file.startsWith("./") ? file : `./${file}`);
45
+ const res = this.getRequire()(this._options.dist, file.startsWith("./") || file.startsWith("https://test.cases/")
46
+ ? file
47
+ : `./${file}`);
46
48
  if (typeof res === "object" && "then" in res) {
47
49
  return res;
48
50
  }
@@ -77,6 +79,15 @@ class BasicRunner {
77
79
  subPath: ""
78
80
  };
79
81
  }
82
+ else if (modulePath.startsWith("https://test.cases/")) {
83
+ const relativePath = (0, urlToRelativePath_1.default)(modulePath);
84
+ const absPath = node_path_1.default.join(currentDirectory, relativePath);
85
+ res = {
86
+ path: absPath,
87
+ content: node_fs_1.default.readFileSync(absPath, "utf-8"),
88
+ subPath: ""
89
+ };
90
+ }
80
91
  else if (isRelativePath(modulePath)) {
81
92
  const p = node_path_1.default.join(currentDirectory, modulePath);
82
93
  res = {
@@ -92,15 +103,6 @@ class BasicRunner {
92
103
  subPath: "absolute_path"
93
104
  };
94
105
  }
95
- else if (modulePath.startsWith("https://test.cases/path/")) {
96
- const relativePath = (0, urlToRelativePath_1.default)(modulePath);
97
- const absPath = node_path_1.default.join(currentDirectory, relativePath);
98
- res = {
99
- path: absPath,
100
- content: node_fs_1.default.readFileSync(absPath, "utf-8"),
101
- subPath: ""
102
- };
103
- }
104
106
  if (this._options.cachable && res) {
105
107
  cached.set(cacheKey, res);
106
108
  }
@@ -5,10 +5,12 @@ declare global {
5
5
  var printLogger: boolean;
6
6
  }
7
7
  export declare class CommonJsRunner<T extends ECompilerType = ECompilerType.Rspack> extends BasicRunner<T> {
8
+ protected requireCache: any;
8
9
  protected createGlobalContext(): IBasicGlobalContext;
9
10
  protected createBaseModuleScope(): IBasicModuleScope;
10
11
  protected createModuleScope(requireFn: TRunnerRequirer, m: TModuleObject, file: TBasicRunnerFile): IBasicModuleScope;
11
12
  protected createRunner(): void;
12
13
  protected createMissRequirer(): TRunnerRequirer;
14
+ protected createJsonRequirer(): TRunnerRequirer;
13
15
  protected createCjsRequirer(): TRunnerRequirer;
14
16
  }
@@ -4,14 +4,15 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.CommonJsRunner = void 0;
7
+ const node_fs_1 = __importDefault(require("node:fs"));
7
8
  const node_path_1 = __importDefault(require("node:path"));
8
9
  const node_vm_1 = __importDefault(require("node:vm"));
9
10
  const basic_1 = require("./basic");
10
- const define = (...args) => {
11
- const factory = args.pop();
12
- factory();
13
- };
14
11
  class CommonJsRunner extends basic_1.BasicRunner {
12
+ constructor() {
13
+ super(...arguments);
14
+ this.requireCache = Object.create(null);
15
+ }
15
16
  createGlobalContext() {
16
17
  return {
17
18
  console: {
@@ -69,6 +70,11 @@ class CommonJsRunner extends basic_1.BasicRunner {
69
70
  });
70
71
  return m;
71
72
  },
73
+ process,
74
+ URL,
75
+ Blob,
76
+ Symbol,
77
+ __MODE__: this._options.compilerOptions.mode,
72
78
  __SNAPSHOT__: node_path_1.default.join(this._options.source, "__snapshot__"),
73
79
  ...this._options.env
74
80
  };
@@ -84,13 +90,13 @@ class CommonJsRunner extends basic_1.BasicRunner {
84
90
  __filename: file.path,
85
91
  _globalAssign: {
86
92
  expect: this._options.env.expect
87
- },
88
- define
93
+ }
89
94
  };
90
95
  }
91
96
  createRunner() {
92
97
  this.requirers.set("miss", this.createMissRequirer());
93
98
  this.requirers.set("entry", this.createCjsRequirer());
99
+ this.requirers.set("json", this.createJsonRequirer());
94
100
  }
95
101
  createMissRequirer() {
96
102
  return (currentDirectory, modulePath, context = {}) => {
@@ -104,8 +110,19 @@ class CommonJsRunner extends basic_1.BasicRunner {
104
110
  : modulePathStr);
105
111
  };
106
112
  }
113
+ createJsonRequirer() {
114
+ return (currentDirectory, modulePath, context = {}) => {
115
+ if (Array.isArray(modulePath)) {
116
+ throw new Error("Array module path is not supported in hot cases");
117
+ }
118
+ const file = context.file || this.getFile(modulePath, currentDirectory);
119
+ if (!file) {
120
+ return this.requirers.get("miss")(currentDirectory, modulePath);
121
+ }
122
+ return JSON.parse(node_fs_1.default.readFileSync(node_path_1.default.join(this._options.dist, modulePath), "utf-8"));
123
+ };
124
+ }
107
125
  createCjsRequirer() {
108
- const requireCache = Object.create(null);
109
126
  return (currentDirectory, modulePath, context = {}) => {
110
127
  if (modulePath === "@rspack/test-tools") {
111
128
  return require("@rspack/test-tools");
@@ -114,16 +131,19 @@ class CommonJsRunner extends basic_1.BasicRunner {
114
131
  if (!file) {
115
132
  return this.requirers.get("miss")(currentDirectory, modulePath);
116
133
  }
117
- if (file.path in requireCache) {
118
- return requireCache[file.path].exports;
134
+ if (file.path.endsWith(".json")) {
135
+ return this.requirers.get("json")(currentDirectory, modulePath, context);
136
+ }
137
+ if (file.path in this.requireCache) {
138
+ return this.requireCache[file.path].exports;
119
139
  }
120
140
  const m = {
121
141
  exports: {}
122
142
  };
123
- requireCache[file.path] = m;
143
+ this.requireCache[file.path] = m;
124
144
  const currentModuleScope = this.createModuleScope(this.getRequire(), m, file);
125
145
  if (this._options.testConfig.moduleScope) {
126
- this._options.testConfig.moduleScope(currentModuleScope);
146
+ this._options.testConfig.moduleScope(currentModuleScope, this._options.stats, this._options.compilerOptions);
127
147
  }
128
148
  if (!this._options.runInNewContext) {
129
149
  file.content = `Object.assign(global, _globalAssign);\n ${file.content}`;
@@ -131,6 +151,12 @@ class CommonJsRunner extends basic_1.BasicRunner {
131
151
  if (file.content.includes("__STATS__") && this._options.stats) {
132
152
  currentModuleScope.__STATS__ = this._options.stats();
133
153
  }
154
+ if (file.content.includes("__STATS_I__")) {
155
+ const statsIndex = this._options.stats?.()?.__index__;
156
+ if (typeof statsIndex === "number") {
157
+ currentModuleScope.__STATS_I__ = statsIndex;
158
+ }
159
+ }
134
160
  const args = Object.keys(currentModuleScope);
135
161
  const argValues = args.map(arg => currentModuleScope[arg]);
136
162
  const code = `(function(${args.join(", ")}) {
@@ -81,6 +81,9 @@ class EsmRunner extends cjs_1.CommonJsRunner {
81
81
  if (!file) {
82
82
  return this.requirers.get("miss")(currentDirectory, modulePath);
83
83
  }
84
+ if (file.content.includes("__STATS__")) {
85
+ esmContext.__STATS__ = this._options.stats?.();
86
+ }
84
87
  let esm = esmCache.get(file.path);
85
88
  if (!esm) {
86
89
  esm = new node_vm_1.SourceTextModule(file.content, {
@@ -11,7 +11,6 @@ export declare class FakeDocumentWebRunner<T extends ECompilerType = ECompilerTy
11
11
  protected createGlobalContext(): import("../../type").IBasicGlobalContext;
12
12
  protected createModuleScope(requireFn: TRunnerRequirer, m: any, file: TBasicRunnerFile): import("../../type").IBasicModuleScope;
13
13
  protected createBaseModuleScope(): import("../../type").IBasicModuleScope;
14
- protected createJsonRequirer(): TRunnerRequirer;
15
14
  protected createRunner(): void;
16
15
  protected preExecute(_: string, file: TBasicRunnerFile): void;
17
16
  protected postExecute(_: Object, file: TBasicRunnerFile): void;
@@ -141,18 +141,6 @@ class FakeDocumentWebRunner extends cjs_1.CommonJsRunner {
141
141
  moduleScope.__dirname = this._options.dist;
142
142
  return moduleScope;
143
143
  }
144
- createJsonRequirer() {
145
- return (currentDirectory, modulePath, context = {}) => {
146
- if (Array.isArray(modulePath)) {
147
- throw new Error("Array module path is not supported in hot cases");
148
- }
149
- const file = context.file || this.getFile(modulePath, currentDirectory);
150
- if (!file) {
151
- return this.requirers.get("miss")(currentDirectory, modulePath);
152
- }
153
- return JSON.parse(node_fs_1.default.readFileSync(node_path_1.default.join(this._options.dist, modulePath), "utf-8"));
154
- };
155
- }
156
144
  createRunner() {
157
145
  super.createRunner();
158
146
  this.requirers.set("cjs", this.getRequire());
@@ -5,7 +5,6 @@ import { CommonJsRunner } from "../cjs";
5
5
  export declare class JSDOMWebRunner<T extends ECompilerType = ECompilerType.Rspack> extends CommonJsRunner<T> {
6
6
  protected _webOptions: IBasicRunnerOptions<T>;
7
7
  private dom;
8
- private requireCache;
9
8
  constructor(_webOptions: IBasicRunnerOptions<T>);
10
9
  run(file: string): Promise<unknown>;
11
10
  getGlobal(name: string): unknown;
@@ -18,7 +18,6 @@ class JSDOMWebRunner extends cjs_1.CommonJsRunner {
18
18
  constructor(_webOptions) {
19
19
  super(_webOptions);
20
20
  this._webOptions = _webOptions;
21
- this.requireCache = Object.create(null);
22
21
  const virtualConsole = new jsdom_1.VirtualConsole();
23
22
  virtualConsole.sendTo(console);
24
23
  this.dom = new jsdom_1.JSDOM(`
@@ -159,7 +158,7 @@ class JSDOMWebRunner extends cjs_1.CommonJsRunner {
159
158
  };
160
159
  const currentModuleScope = this.createModuleScope(this.getRequire(), m, file);
161
160
  if (this._options.testConfig.moduleScope) {
162
- this._options.testConfig.moduleScope(currentModuleScope);
161
+ this._options.testConfig.moduleScope(currentModuleScope, this._options.stats, this._options.compilerOptions);
163
162
  }
164
163
  const scopeKey = (0, helper_1.escapeSep)(file.path);
165
164
  const args = Object.keys(currentModuleScope).filter(arg => !["window", "self", "globalThis", "console"].includes(arg));
@@ -231,7 +231,7 @@ class BasicCaseCreator {
231
231
  };
232
232
  }
233
233
  createEnv(testConfig) {
234
- if (typeof this._options.runner === "function" && !testConfig.noTest) {
234
+ if (typeof this._options.runner === "function" && !testConfig.noTests) {
235
235
  return (0, createLazyTestEnv_1.default)(10000);
236
236
  }
237
237
  return {
package/dist/type.d.ts CHANGED
@@ -135,12 +135,12 @@ export declare enum EDocumentType {
135
135
  export type TTestConfig<T extends ECompilerType> = {
136
136
  documentType?: EDocumentType;
137
137
  validate?: (stats: TCompilerStats<T> | TCompilerMultiStats<T>, stderr?: string) => void;
138
- noTest?: boolean;
138
+ noTests?: boolean;
139
139
  writeStatsOuptut?: boolean;
140
140
  writeStatsJson?: boolean;
141
- beforeExecute?: () => void;
142
- afterExecute?: () => void;
143
- moduleScope?: (ms: IBasicModuleScope, stats?: TCompilerStatsCompilation<T>) => IBasicModuleScope;
141
+ beforeExecute?: (options: TCompilerOptions<T>) => void;
142
+ afterExecute?: (options: TCompilerOptions<T>) => void;
143
+ moduleScope?: (ms: IBasicModuleScope, stats?: TCompilerStatsCompilation<T>, options?: TCompilerOptions<T>) => IBasicModuleScope;
144
144
  checkStats?: (stepName: string, jsonStats: TCompilerStatsCompilation<T> | undefined, stringStats: String) => boolean;
145
145
  findBundle?: (index: number, options: TCompilerOptions<T>, stepName?: string) => string | string[];
146
146
  bundlePath?: string[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rspack-canary/test-tools",
3
- "version": "1.5.4-canary-55493775-20250914174633",
3
+ "version": "1.5.5-canary-f4d631e6-20250915072424",
4
4
  "license": "MIT",
5
5
  "description": "Test tools for rspack",
6
6
  "main": "dist/index.js",
@@ -100,10 +100,10 @@
100
100
  "wast-loader": "^1.14.1",
101
101
  "worker-rspack-loader": "^3.1.2",
102
102
  "exports-loader": "^5.0.0",
103
- "@rspack/cli": "npm:@rspack-canary/cli@1.5.4-canary-55493775-20250914174633",
104
- "@rspack/core": "npm:@rspack-canary/core@1.5.4-canary-55493775-20250914174633",
103
+ "@rspack/cli": "npm:@rspack-canary/cli@1.5.5-canary-f4d631e6-20250915072424",
105
104
  "@rspack/binding-testing": "1.4.1",
106
- "@rspack/test-tools": "npm:@rspack-canary/test-tools@1.5.4-canary-55493775-20250914174633"
105
+ "@rspack/test-tools": "npm:@rspack-canary/test-tools@1.5.5-canary-f4d631e6-20250915072424",
106
+ "@rspack/core": "npm:@rspack-canary/core@1.5.5-canary-f4d631e6-20250915072424"
107
107
  },
108
108
  "peerDependencies": {
109
109
  "@rspack/core": ">=1.0.0"