@rspack/test-tools 1.5.8 → 1.6.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (134) hide show
  1. package/dist/case/builtin.js +0 -22
  2. package/dist/case/cache.d.ts +1 -1
  3. package/dist/case/cache.js +5 -5
  4. package/dist/case/common.d.ts +1 -0
  5. package/dist/case/common.js +17 -10
  6. package/dist/case/config.js +5 -3
  7. package/dist/case/diagnostic.d.ts +2 -2
  8. package/dist/case/diagnostic.js +2 -3
  9. package/dist/case/error.d.ts +1 -0
  10. package/dist/case/error.js +25 -6
  11. package/dist/case/esm-output.js +28 -2
  12. package/dist/case/example.d.ts +1 -0
  13. package/dist/case/example.js +57 -0
  14. package/dist/case/hash.js +1 -2
  15. package/dist/case/hook.js +3 -4
  16. package/dist/case/hot-step.d.ts +1 -1
  17. package/dist/case/hot-step.js +12 -13
  18. package/dist/case/hot.d.ts +5 -4
  19. package/dist/case/hot.js +61 -83
  20. package/dist/case/incremental.d.ts +2 -2
  21. package/dist/case/incremental.js +8 -27
  22. package/dist/case/index.d.ts +12 -1
  23. package/dist/case/index.js +7 -1
  24. package/dist/case/multi-compiler.d.ts +18 -0
  25. package/dist/case/multi-compiler.js +98 -0
  26. package/dist/case/normal.d.ts +2 -0
  27. package/dist/case/normal.js +22 -12
  28. package/dist/case/runner.d.ts +1 -1
  29. package/dist/case/runner.js +4 -3
  30. package/dist/case/stats-api.d.ts +9 -0
  31. package/dist/case/stats-output.js +5 -4
  32. package/dist/case/watch.d.ts +5 -5
  33. package/dist/case/watch.js +11 -16
  34. package/dist/compare/compare.js +6 -3
  35. package/dist/helper/directory.js +1 -1
  36. package/dist/helper/expect/error.js +1 -1
  37. package/dist/helper/expect/placeholder.js +7 -7
  38. package/dist/helper/expect/to-match-file-snapshot.d.ts +0 -1
  39. package/dist/helper/hot-update/loader.d.ts +2 -1
  40. package/dist/helper/hot-update/loader.js +5 -30
  41. package/dist/helper/hot-update/plugin.d.ts +1 -1
  42. package/dist/helper/hot-update/plugin.js +14 -13
  43. package/dist/helper/legacy/LogTestPlugin.d.ts +6 -0
  44. package/dist/helper/legacy/LogTestPlugin.js +35 -0
  45. package/dist/helper/legacy/asModule.js +0 -2
  46. package/dist/helper/legacy/createLazyTestEnv.d.ts +1 -0
  47. package/dist/helper/legacy/createLazyTestEnv.js +4 -3
  48. package/dist/helper/legacy/supportsTextDecoder.js +9 -0
  49. package/dist/helper/read-config-file.d.ts +2 -2
  50. package/dist/helper/read-config-file.js +5 -2
  51. package/dist/helper/setup-env.js +18 -2
  52. package/dist/helper/util/checkStats.d.ts +0 -1
  53. package/dist/helper/util/checkStats.js +0 -18
  54. package/dist/helper/util/expectWarningFactory.js +2 -4
  55. package/dist/index.d.ts +0 -1
  56. package/dist/index.js +0 -1
  57. package/dist/jest/ignore-snapshot-default-reporter.d.ts +2 -0
  58. package/dist/jest/ignore-snapshot-default-reporter.js +57 -0
  59. package/dist/jest/ignore-snapshot-summary-reporter.d.ts +2 -0
  60. package/dist/jest/ignore-snapshot-summary-reporter.js +24 -0
  61. package/dist/jest/patch-node-env.d.ts +5 -0
  62. package/dist/jest/patch-node-env.js +18 -0
  63. package/dist/jest/slash.d.ts +2 -0
  64. package/dist/jest/slash.js +16 -0
  65. package/dist/runner/node/index.js +12 -3
  66. package/dist/runner/web/index.d.ts +20 -7
  67. package/dist/runner/web/index.js +293 -18
  68. package/dist/test/creator.js +15 -10
  69. package/dist/test/tester.d.ts +1 -0
  70. package/dist/test/tester.js +21 -4
  71. package/dist/type.d.ts +14 -5
  72. package/dist/type.js +1 -6
  73. package/jest.d.ts +2 -0
  74. package/package.json +10 -41
  75. package/dist/helper/legacy/FakeDocument.d.ts +0 -54
  76. package/dist/helper/legacy/FakeDocument.js +0 -280
  77. package/dist/helper/legacy/createLogger.d.ts +0 -23
  78. package/dist/helper/legacy/createLogger.js +0 -20
  79. package/dist/helper/legacy/supportsBlob.js +0 -10
  80. package/dist/helper/legacy/supportsClassFields.d.ts +0 -2
  81. package/dist/helper/legacy/supportsClassFields.js +0 -11
  82. package/dist/helper/legacy/supportsES6.d.ts +0 -2
  83. package/dist/helper/legacy/supportsES6.js +0 -11
  84. package/dist/helper/legacy/supportsForOf.d.ts +0 -2
  85. package/dist/helper/legacy/supportsForOf.js +0 -11
  86. package/dist/helper/legacy/supportsIteratorDestructuring.d.ts +0 -2
  87. package/dist/helper/legacy/supportsIteratorDestructuring.js +0 -11
  88. package/dist/helper/legacy/supportsLogicalAssignment.d.ts +0 -2
  89. package/dist/helper/legacy/supportsLogicalAssignment.js +0 -11
  90. package/dist/helper/legacy/supportsObjectDestructuring.d.ts +0 -2
  91. package/dist/helper/legacy/supportsObjectDestructuring.js +0 -11
  92. package/dist/helper/legacy/supportsOptionalCatchBinding.d.ts +0 -2
  93. package/dist/helper/legacy/supportsOptionalCatchBinding.js +0 -11
  94. package/dist/helper/legacy/supportsOptionalChaining.d.ts +0 -2
  95. package/dist/helper/legacy/supportsOptionalChaining.js +0 -11
  96. package/dist/helper/legacy/supportsRequireInModule.d.ts +0 -2
  97. package/dist/helper/legacy/supportsRequireInModule.js +0 -5
  98. package/dist/helper/legacy/supportsResponse.d.ts +0 -2
  99. package/dist/helper/legacy/supportsResponse.js +0 -10
  100. package/dist/helper/legacy/supportsSpread.d.ts +0 -2
  101. package/dist/helper/legacy/supportsSpread.js +0 -12
  102. package/dist/helper/legacy/supportsTemplateStrings.d.ts +0 -2
  103. package/dist/helper/legacy/supportsTemplateStrings.js +0 -11
  104. package/dist/helper/legacy/supportsWebAssembly.d.ts +0 -2
  105. package/dist/helper/legacy/supportsWebAssembly.js +0 -10
  106. package/dist/helper/legacy/supportsWorker.d.ts +0 -2
  107. package/dist/helper/legacy/supportsWorker.js +0 -17
  108. package/dist/helper/legacy/walkCssTokens.d.ts +0 -40
  109. package/dist/helper/legacy/walkCssTokens.js +0 -761
  110. package/dist/helper/legacy/warmup-webpack.d.ts +0 -1
  111. package/dist/helper/legacy/warmup-webpack.js +0 -26
  112. package/dist/helper/loaders/hot-update.d.ts +0 -1
  113. package/dist/helper/loaders/hot-update.js +0 -40
  114. package/dist/helper/plugins/hot-update.d.ts +0 -7
  115. package/dist/helper/plugins/hot-update.js +0 -40
  116. package/dist/helper/plugins/index.d.ts +0 -1
  117. package/dist/helper/plugins/index.js +0 -17
  118. package/dist/helper/util/currentWatchStep.d.ts +0 -1
  119. package/dist/helper/util/currentWatchStep.js +0 -2
  120. package/dist/helper/util/identifier.d.ts +0 -76
  121. package/dist/helper/util/identifier.js +0 -339
  122. package/dist/helper/util/replaceMitteDiagnostic.d.ts +0 -2
  123. package/dist/helper/util/replaceMitteDiagnostic.js +0 -17
  124. package/dist/reporter/diff-html.d.ts +0 -15
  125. package/dist/reporter/diff-html.js +0 -69
  126. package/dist/reporter/diff-stats.d.ts +0 -24
  127. package/dist/reporter/diff-stats.js +0 -131
  128. package/dist/reporter/index.d.ts +0 -2
  129. package/dist/reporter/index.js +0 -18
  130. package/dist/runner/web/fake.d.ts +0 -15
  131. package/dist/runner/web/fake.js +0 -213
  132. package/dist/runner/web/jsdom.d.ts +0 -24
  133. package/dist/runner/web/jsdom.js +0 -228
  134. /package/dist/helper/legacy/{supportsBlob.d.ts → supportsTextDecoder.d.ts} +0 -0
package/dist/index.js CHANGED
@@ -18,7 +18,6 @@ __exportStar(require("./case"), exports);
18
18
  __exportStar(require("./compare"), exports);
19
19
  __exportStar(require("./helper"), exports);
20
20
  __exportStar(require("./plugin"), exports);
21
- __exportStar(require("./reporter"), exports);
22
21
  __exportStar(require("./runner"), exports);
23
22
  __exportStar(require("./test/context"), exports);
24
23
  __exportStar(require("./test/creator"), exports);
@@ -0,0 +1,2 @@
1
+ export = DefaultReporter;
2
+ import { DefaultReporter } from "@jest/reporters";
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ // @ts-nocheck
3
+ const { DefaultReporter } = require("@jest/reporters");
4
+ const chalk = require.cache[require.resolve("@jest/reporters")].require("chalk");
5
+ const jestUtil = require.cache[require.resolve("@jest/reporters")].require("jest-util");
6
+ const ARROW = " \u203A ";
7
+ const DOT = " \u2022 ";
8
+ const FAIL_COLOR = chalk.bold.red;
9
+ const SNAPSHOT_ADDED = chalk.bold.green;
10
+ const SNAPSHOT_UPDATED = chalk.bold.green;
11
+ const SNAPSHOT_OUTDATED = chalk.bold.yellow;
12
+ function getSnapshotStatus(snapshot, afterUpdate) {
13
+ const statuses = [];
14
+ if (snapshot.added) {
15
+ statuses.push(SNAPSHOT_ADDED(`${ARROW + jestUtil.pluralize("snapshot", snapshot.added)} written.`));
16
+ }
17
+ if (snapshot.updated) {
18
+ statuses.push(SNAPSHOT_UPDATED(`${ARROW + jestUtil.pluralize("snapshot", snapshot.updated)} updated.`));
19
+ }
20
+ if (snapshot.unmatched) {
21
+ statuses.push(FAIL_COLOR(`${ARROW + jestUtil.pluralize("snapshot", snapshot.unmatched)} failed.`));
22
+ }
23
+ if (snapshot.unchecked) {
24
+ if (afterUpdate) {
25
+ statuses.push(SNAPSHOT_UPDATED(`${ARROW + jestUtil.pluralize("snapshot", snapshot.unchecked)} removed.`));
26
+ for (const key of snapshot.uncheckedKeys) {
27
+ statuses.push(` ${DOT}${key}`);
28
+ }
29
+ }
30
+ else {
31
+ statuses.push(`${SNAPSHOT_OUTDATED(`${ARROW + jestUtil.pluralize("snapshot", snapshot.unchecked)} obsolete`)}.`);
32
+ }
33
+ }
34
+ if (snapshot.fileDeleted) {
35
+ statuses.push(SNAPSHOT_UPDATED(`${ARROW}snapshot file removed.`));
36
+ }
37
+ return statuses;
38
+ }
39
+ const isUpdate = process.argv.includes("-u") || process.argv.includes("--updateSnapshot");
40
+ const isFiltering = process.argv.includes("-t") || process.argv.includes("--testNamePattern");
41
+ const isVerbose = process.argv.includes("--verbose");
42
+ if (!isVerbose && !isUpdate && isFiltering) {
43
+ class IgnoreSnapshotDefaultReporter extends DefaultReporter {
44
+ printTestFileFailureMessage(_testPath, _config, result) {
45
+ if (result.failureMessage) {
46
+ this.log(result.failureMessage);
47
+ }
48
+ const didUpdate = this._globalConfig.updateSnapshot === "all";
49
+ const snapshotStatuses = getSnapshotStatus(result.snapshot, didUpdate);
50
+ snapshotStatuses.forEach(this.log);
51
+ }
52
+ }
53
+ module.exports = IgnoreSnapshotDefaultReporter;
54
+ }
55
+ else {
56
+ module.exports = DefaultReporter;
57
+ }
@@ -0,0 +1,2 @@
1
+ export = SummaryReporter;
2
+ import { SummaryReporter } from "@jest/reporters";
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ // @ts-nocheck
3
+ const { SummaryReporter } = require("@jest/reporters");
4
+ const chalk = require.cache[require.resolve("@jest/reporters")].require("chalk");
5
+ const isUpdate = process.argv.includes("-u") || process.argv.includes("--updateSnapshot");
6
+ const isFiltering = process.argv.includes("-t") || process.argv.includes("--testNamePattern");
7
+ const isVerbose = process.argv.includes("--verbose");
8
+ if (!isVerbose && !isUpdate && isFiltering) {
9
+ class IgnoreSnapshotSummaryReporter extends SummaryReporter {
10
+ _printSnapshotSummary(snapshots, globalConfig) {
11
+ if (snapshots.added ||
12
+ snapshots.filesRemoved ||
13
+ snapshots.unchecked ||
14
+ snapshots.unmatched ||
15
+ snapshots.updated) {
16
+ this.log(chalk.bold.yellow("Some snapshots are obsoleted, flush with `npm run test -- -u` if necessary.\n"));
17
+ }
18
+ }
19
+ }
20
+ module.exports = IgnoreSnapshotSummaryReporter;
21
+ }
22
+ else {
23
+ module.exports = SummaryReporter;
24
+ }
@@ -0,0 +1,5 @@
1
+ export = CustomEnvironment;
2
+ declare const CustomEnvironment_base: typeof import("jest-environment-node").default;
3
+ declare class CustomEnvironment extends CustomEnvironment_base {
4
+ handleTestEvent(event: any, state: any): Promise<void>;
5
+ }
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ // @ts-nocheck
3
+ // Copied from <https://github.com/webpack/webpack/blob/main/test/patch-node-env.js>
4
+ //
5
+ const NodeEnvironment =
6
+ // For jest@29
7
+ require("jest-environment-node").TestEnvironment ||
8
+ // For jest@27
9
+ require("jest-environment-node");
10
+ class CustomEnvironment extends NodeEnvironment {
11
+ // Workaround for `Symbol('JEST_STATE_SYMBOL')`
12
+ async handleTestEvent(event, state) {
13
+ if (!this.global.JEST_STATE_SYMBOL) {
14
+ this.global.JEST_STATE_SYMBOL = state;
15
+ }
16
+ }
17
+ }
18
+ module.exports = CustomEnvironment;
@@ -0,0 +1,2 @@
1
+ declare function _exports(path: any): any;
2
+ export = _exports;
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ // @ts-nocheck
3
+ /**
4
+ * The following code is copied from
5
+ * https://github.com/sindresorhus/slash/blob/98b618f5a3bfcb5dd374b204868818845b87bb2f/index.js
6
+ *
7
+ * MIT Licensed
8
+ * Author Sindre Sorhus @sindresorhus
9
+ */
10
+ module.exports = function slash(path) {
11
+ const isExtendedLengthPath = path.startsWith("\\\\?\\");
12
+ if (isExtendedLengthPath) {
13
+ return path;
14
+ }
15
+ return path.replace(/\\/g, "/");
16
+ };
@@ -42,6 +42,7 @@ const node_path_1 = __importDefault(require("node:path"));
42
42
  const node_url_1 = require("node:url");
43
43
  const node_vm_1 = __importStar(require("node:vm"));
44
44
  const asModule_1 = __importDefault(require("../../helper/legacy/asModule"));
45
+ const createFakeWorker_1 = __importDefault(require("../../helper/legacy/createFakeWorker"));
45
46
  const urlToRelativePath_1 = __importDefault(require("../../helper/legacy/urlToRelativePath"));
46
47
  const type_1 = require("../../type");
47
48
  const isRelativePath = (p) => /^\.\.?\//.test(p);
@@ -163,8 +164,12 @@ class NodeRunner {
163
164
  Symbol,
164
165
  Buffer,
165
166
  setImmediate,
167
+ self: this.globalContext,
166
168
  __MODE__: this._options.compilerOptions.mode,
167
169
  __SNAPSHOT__: node_path_1.default.join(this._options.source, "__snapshot__"),
170
+ Worker: (0, createFakeWorker_1.default)(this._options.env, {
171
+ outputDirectory: this._options.dist
172
+ }),
168
173
  ...this._options.env
169
174
  };
170
175
  return baseModuleScope;
@@ -303,7 +308,7 @@ class NodeRunner {
303
308
  };
304
309
  this.requireCache[file.path] = m;
305
310
  if (!this._options.runInNewContext) {
306
- file.content = `Object.assign(global, _globalAssign);\n ${file.content}`;
311
+ file.content = `Object.assign(global, _globalAssign);${file.content}`;
307
312
  }
308
313
  const currentModuleScope = this.createModuleScope(this.getRequire(), m, file);
309
314
  if (this._options.testConfig.moduleScope) {
@@ -352,6 +357,12 @@ class NodeRunner {
352
357
  if (file.content.includes("__STATS__")) {
353
358
  esmContext.__STATS__ = this._options.stats?.();
354
359
  }
360
+ if (file.content.includes("__STATS_I__")) {
361
+ const statsIndex = this._options.stats?.()?.__index__;
362
+ if (typeof statsIndex === "number") {
363
+ esmContext.__STATS_I__ = statsIndex;
364
+ }
365
+ }
355
366
  let esm = esmCache.get(file.path);
356
367
  if (!esm) {
357
368
  esm = new node_vm_1.SourceTextModule(file.content, {
@@ -385,8 +396,6 @@ class NodeRunner {
385
396
  }), referencingModule.context, true);
386
397
  });
387
398
  }
388
- if (esm.instantiate)
389
- esm.instantiate();
390
399
  await esm.evaluate();
391
400
  if (context.esmMode === type_1.EEsmMode.Evaluated) {
392
401
  return esm;
@@ -1,14 +1,27 @@
1
- import { type ECompilerType, EDocumentType, type ITestRunner } from "../../type";
2
- import type { INodeRunnerOptions, NodeRunner } from "../node";
1
+ import type { ECompilerType, TRunnerFile, TRunnerRequirer } from "../../type";
2
+ import { type INodeRunnerOptions, NodeRunner } from "../node";
3
3
  export interface IWebRunnerOptions<T extends ECompilerType = ECompilerType.Rspack> extends INodeRunnerOptions<T> {
4
- dom: EDocumentType;
4
+ location: string;
5
5
  }
6
- export declare class WebRunner<T extends ECompilerType = ECompilerType.Rspack> implements ITestRunner {
6
+ export declare class WebRunner<T extends ECompilerType = ECompilerType.Rspack> extends NodeRunner<T> {
7
7
  protected _webOptions: IWebRunnerOptions<T>;
8
- protected originMethods: Partial<NodeRunner<T>>;
9
- private implement;
8
+ private dom;
10
9
  constructor(_webOptions: IWebRunnerOptions<T>);
11
10
  run(file: string): Promise<unknown>;
12
- getRequire(): import("../../type").TRunnerRequirer;
13
11
  getGlobal(name: string): unknown;
12
+ protected createResourceLoader(): {
13
+ fetch(url: string, _: {
14
+ element: HTMLScriptElement;
15
+ }): any;
16
+ };
17
+ private urlToPath;
18
+ protected createBaseModuleScope(): import("../../type").IModuleScope;
19
+ protected getModuleContent(file: TRunnerFile): [
20
+ {
21
+ exports: Record<string, unknown>;
22
+ },
23
+ string
24
+ ];
25
+ protected createJSDOMRequirer(): TRunnerRequirer;
26
+ protected createRunner(): void;
14
27
  }
@@ -1,32 +1,307 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.WebRunner = void 0;
4
- const type_1 = require("../../type");
5
- const fake_1 = require("./fake");
6
- const jsdom_1 = require("./jsdom");
7
- class WebRunner {
7
+ const node_fs_1 = __importDefault(require("node:fs"));
8
+ const node_path_1 = __importDefault(require("node:path"));
9
+ const node_url_1 = require("node:url");
10
+ const node_vm_1 = require("node:vm");
11
+ const jsdom_1 = require("jsdom");
12
+ const helper_1 = require("../../helper");
13
+ const EventSourceForNode_1 = __importDefault(require("../../helper/legacy/EventSourceForNode"));
14
+ const urlToRelativePath_1 = __importDefault(require("../../helper/legacy/urlToRelativePath"));
15
+ const node_1 = require("../node");
16
+ const EVAL_LOCATION_REGEX = /<anonymous>:(\d+)/;
17
+ // Compatibility code to suppress iconv-lite warnings
18
+ require("iconv-lite").skipDecodeWarning = true;
19
+ const FAKE_HOSTS = [
20
+ "https://example.com/public/path",
21
+ "https://example.com",
22
+ "https://test.cases/path/",
23
+ "https://test.cases/server/",
24
+ "https://test.cases"
25
+ ];
26
+ const FAKE_TEST_ROOT_HOST = "https://test.cases/root/";
27
+ class WebRunner extends node_1.NodeRunner {
8
28
  constructor(_webOptions) {
29
+ super(_webOptions);
9
30
  this._webOptions = _webOptions;
10
- this.originMethods = {};
11
- const { dom } = _webOptions;
12
- if (dom === type_1.EDocumentType.Fake) {
13
- this.implement = new fake_1.FakeDocumentWebRunner(_webOptions);
31
+ const virtualConsole = new jsdom_1.VirtualConsole({});
32
+ virtualConsole.sendTo(console, {
33
+ omitJSDOMErrors: true
34
+ });
35
+ this.dom = new jsdom_1.JSDOM(`
36
+ <!doctype html>
37
+ <html>
38
+ <head></head>
39
+ <body></body>
40
+ </html>
41
+ `, {
42
+ url: this._webOptions.location,
43
+ resources: this.createResourceLoader(),
44
+ runScripts: "dangerously",
45
+ virtualConsole
46
+ });
47
+ this.dom.window.console = console;
48
+ // compat with FakeDocument
49
+ this.dom.window.eval(`
50
+ Object.defineProperty(document.head, "_children", {
51
+ get: function() {
52
+ return Array.from(document.head.children).map(function(ele) {
53
+ var type = ele.tagName.toLowerCase();
54
+ return new Proxy(ele, {
55
+ get(target, prop, receiver) {
56
+ if (prop === "_type") {
57
+ return target.tagName.toLowerCase();
58
+ }
59
+ if (prop === "_href") {
60
+ return Reflect.get(target, "href", receiver);
61
+ }
62
+ return Reflect.get(target, prop, receiver);
63
+ },
64
+ });
65
+ });
14
66
  }
15
- else if (dom === type_1.EDocumentType.JSDOM) {
16
- this.implement = new jsdom_1.JSDOMWebRunner(_webOptions);
17
- }
18
- else {
19
- throw new Error(`Dom type "${dom}" of web runner is not support yet`);
67
+ });
68
+ `);
69
+ if (this._options.compilerOptions.node !== false) {
70
+ const vmContext = this.dom.getInternalVMContext();
71
+ vmContext.global = {};
20
72
  }
21
73
  }
22
74
  run(file) {
23
- return this.implement.run(file);
24
- }
25
- getRequire() {
26
- return this.implement.getRequire();
75
+ if (!file.endsWith(".js") && !file.endsWith(".mjs")) {
76
+ const cssElement = this.dom.window.document.createElement("link");
77
+ cssElement.href = file;
78
+ cssElement.rel = "stylesheet";
79
+ this.dom.window.document.head.appendChild(cssElement);
80
+ return Promise.resolve();
81
+ }
82
+ return super.run(file);
27
83
  }
28
84
  getGlobal(name) {
29
- return this.implement.getGlobal(name);
85
+ return this.globalContext[name];
86
+ }
87
+ createResourceLoader() {
88
+ const that = this;
89
+ class CustomResourceLoader extends jsdom_1.ResourceLoader {
90
+ fetch(url, _) {
91
+ const filePath = that.urlToPath(url);
92
+ let finalCode;
93
+ if (node_path_1.default.extname(filePath) === ".js") {
94
+ const currentDirectory = node_path_1.default.dirname(filePath);
95
+ const file = that.getFile(filePath, currentDirectory);
96
+ if (!file) {
97
+ throw new Error(`File not found: ${filePath}`);
98
+ }
99
+ const [_m, code] = that.getModuleContent(file);
100
+ finalCode = code;
101
+ }
102
+ else {
103
+ finalCode = node_fs_1.default.readFileSync(filePath);
104
+ }
105
+ try {
106
+ that.dom.window["__LINK_SHEET__"] ??= {};
107
+ that.dom.window["__LINK_SHEET__"][url] = finalCode.toString();
108
+ return Promise.resolve(finalCode);
109
+ }
110
+ catch (err) {
111
+ console.error(err);
112
+ if (err.code === "ENOENT") {
113
+ return null;
114
+ }
115
+ throw err;
116
+ }
117
+ }
118
+ }
119
+ return new CustomResourceLoader();
120
+ }
121
+ urlToPath(url) {
122
+ if (url.startsWith("file://")) {
123
+ return (0, node_url_1.fileURLToPath)(url);
124
+ }
125
+ if (url.startsWith(FAKE_TEST_ROOT_HOST)) {
126
+ return node_path_1.default.resolve(__TEST_PATH__, `./${url.slice(FAKE_TEST_ROOT_HOST.length)}`);
127
+ }
128
+ let dist = url;
129
+ for (const host of FAKE_HOSTS) {
130
+ if (url.startsWith(host)) {
131
+ dist = url.slice(host.length);
132
+ break;
133
+ }
134
+ }
135
+ return node_path_1.default.resolve(this._webOptions.dist, `./${dist}`).split("?")[0];
136
+ }
137
+ createBaseModuleScope() {
138
+ const moduleScope = super.createBaseModuleScope();
139
+ moduleScope.EventSource = EventSourceForNode_1.default;
140
+ moduleScope.fetch = async (url) => {
141
+ try {
142
+ const buffer = await new Promise((resolve, reject) => node_fs_1.default.readFile(this.urlToPath(url), (err, b) => err ? reject(err) : resolve(b)));
143
+ return {
144
+ status: 200,
145
+ ok: true,
146
+ json: async () => JSON.parse(buffer.toString("utf-8"))
147
+ };
148
+ }
149
+ catch (err) {
150
+ if (err.code === "ENOENT") {
151
+ return {
152
+ status: 404,
153
+ ok: false
154
+ };
155
+ }
156
+ throw err;
157
+ }
158
+ };
159
+ moduleScope.URL = URL;
160
+ moduleScope.importScripts = (url) => {
161
+ this._options.env.expect(url).toMatch(/^https:\/\/test\.cases\/path\//);
162
+ this.requirers.get("entry")(this._options.dist, (0, urlToRelativePath_1.default)(url));
163
+ };
164
+ moduleScope.getComputedStyle = (element) => {
165
+ const computedStyle = this.dom.window.getComputedStyle(element);
166
+ const getPropertyValue = computedStyle.getPropertyValue.bind(computedStyle);
167
+ return {
168
+ ...computedStyle,
169
+ getPropertyValue(v) {
170
+ return getPropertyValue(v);
171
+ }
172
+ };
173
+ };
174
+ moduleScope.window = this.dom.window;
175
+ moduleScope.document = this.dom.window.document;
176
+ moduleScope.getLinkSheet = (link) => {
177
+ return this.dom.window["__LINK_SHEET__"][link.href];
178
+ };
179
+ return moduleScope;
180
+ }
181
+ getModuleContent(file) {
182
+ const m = {
183
+ exports: {}
184
+ };
185
+ const currentModuleScope = this.createModuleScope(this.getRequire(), m, file);
186
+ if (this._options.testConfig.moduleScope) {
187
+ this._options.testConfig.moduleScope(currentModuleScope, this._options.stats, this._options.compilerOptions);
188
+ }
189
+ if (file.content.includes("__STATS__")) {
190
+ currentModuleScope.__STATS__ = this._options.stats?.();
191
+ }
192
+ if (file.content.includes("__STATS_I__")) {
193
+ const statsIndex = this._options.stats?.()?.__index__;
194
+ if (typeof statsIndex === "number") {
195
+ currentModuleScope.__STATS_I__ = statsIndex;
196
+ }
197
+ }
198
+ const createLocatedError = (e, file) => {
199
+ const match = (e.stack || e.message).match(EVAL_LOCATION_REGEX);
200
+ if (match) {
201
+ const [, line] = match;
202
+ const realLine = Number(line) - 34;
203
+ const codeLines = file.content.split("\n");
204
+ const lineContents = [
205
+ ...codeLines
206
+ .slice(Math.max(0, realLine - 3), Math.max(0, realLine - 1))
207
+ .map(line => `│ ${line}`),
208
+ `│> ${codeLines[realLine - 1]}`,
209
+ ...codeLines.slice(realLine, realLine + 2).map(line => `│ ${line}`)
210
+ ];
211
+ const message = `Error in JSDOM when running file '${file.path}' at line ${realLine}: ${e.message}\n${lineContents.join("\n")}`;
212
+ const finalError = new Error(message);
213
+ finalError.stack = undefined;
214
+ return finalError;
215
+ }
216
+ else {
217
+ return e;
218
+ }
219
+ };
220
+ const originIt = currentModuleScope.it;
221
+ currentModuleScope.it = (description, fn) => {
222
+ originIt(description, async () => {
223
+ try {
224
+ await fn();
225
+ }
226
+ catch (err) {
227
+ throw createLocatedError(err, file);
228
+ }
229
+ });
230
+ };
231
+ const scopeKey = (0, helper_1.escapeSep)(file.path);
232
+ const args = Object.keys(currentModuleScope).filter(arg => !["window", "self", "globalThis", "console"].includes(arg));
233
+ const argValues = args
234
+ .map(arg => `window["${scopeKey}"]["${arg}"]`)
235
+ .join(", ");
236
+ this.dom.window[scopeKey] = currentModuleScope;
237
+ this.dom.window["__GLOBAL_SHARED__"] = this.globalContext;
238
+ this.dom.window["__FILE__"] = file;
239
+ this.dom.window["__CREATE_LOCATED_ERROR__"] = createLocatedError;
240
+ return [
241
+ m,
242
+ `// hijack document.currentScript for auto public path
243
+ var $$g$$ = new Proxy(window, {
244
+ get(target, prop, receiver) {
245
+ if (prop === "document") {
246
+ return new Proxy(window.document, {
247
+ get(target, prop, receiver) {
248
+ if (prop === "currentScript") {
249
+ var script = target.createElement("script");
250
+ script.src = "https://test.cases/path/${(0, helper_1.escapeSep)(file.subPath)}index.js";
251
+ return script;
252
+ }
253
+ return Reflect.get(target, prop, receiver);
254
+ }
255
+ });
256
+ }
257
+ return Reflect.get(target, prop, receiver);
258
+ },
259
+ });
260
+ var $$self$$ = new Proxy(window, {
261
+ get(target, prop, receiver) {
262
+ if (prop === "__HMR_UPDATED_RUNTIME__") {
263
+ return window["__GLOBAL_SHARED__"]["__HMR_UPDATED_RUNTIME__"];
264
+ }
265
+ return Reflect.get(target, prop, receiver);
266
+ },
267
+ set(target, prop, value, receiver) {
268
+ if (prop === "__HMR_UPDATED_RUNTIME__") {
269
+ window["__GLOBAL_SHARED__"]["__HMR_UPDATED_RUNTIME__"] = value;
270
+ }
271
+ return Reflect.set(target, prop, value, receiver);
272
+ }
273
+ });
274
+ (function(window, self, globalThis, console, ${args.join(", ")}) {
275
+ try {
276
+ ${file.content}
277
+ } catch (err) {
278
+ throw __CREATE_LOCATED_ERROR__(err, __FILE__);
279
+ }
280
+ })($$g$$, $$self$$, $$g$$, window["console"], ${argValues});`
281
+ ];
282
+ }
283
+ createJSDOMRequirer() {
284
+ return (currentDirectory, modulePath, context = {}) => {
285
+ const file = context.file || this.getFile(modulePath, currentDirectory);
286
+ if (!file) {
287
+ return this.requirers.get("miss")(currentDirectory, modulePath);
288
+ }
289
+ if (file.path in this.requireCache) {
290
+ return this.requireCache[file.path].exports;
291
+ }
292
+ const [m, code] = this.getModuleContent(file);
293
+ this.preExecute(code, file);
294
+ const script = new node_vm_1.Script(code);
295
+ const vmContext = this.dom.getInternalVMContext();
296
+ script.runInContext(vmContext);
297
+ this.postExecute(m, file);
298
+ this.requireCache[file.path] = m;
299
+ return m.exports;
300
+ };
301
+ }
302
+ createRunner() {
303
+ super.createRunner();
304
+ this.requirers.set("cjs", this.createJSDOMRequirer());
30
305
  }
31
306
  }
32
307
  exports.WebRunner = WebRunner;
@@ -97,17 +97,19 @@ class BasicCaseCreator {
97
97
  : index
98
98
  ? `step [${index}] should pass`
99
99
  : "should pass";
100
- it(description, cb => {
101
- stepSignal.then((e) => {
102
- cb(e);
103
- });
104
- }, options.timeout || 180000);
100
+ it(description, async () => {
101
+ const e = await stepSignal;
102
+ if (e) {
103
+ throw e;
104
+ }
105
+ }, options.timeout || 300000);
105
106
  chain = chain.then(async () => {
106
107
  try {
107
108
  env.clear();
108
109
  await tester.compile();
109
110
  await tester.check(env);
110
111
  await env.run();
112
+ await tester.after();
111
113
  const context = tester.getContext();
112
114
  if (!tester.next() && context.hasError()) {
113
115
  const errors = context
@@ -170,7 +172,7 @@ class BasicCaseCreator {
170
172
  .join("\n\n");
171
173
  throw new Error(`Case "${name}" failed at step ${tester.step + 1}:\n${errors}`);
172
174
  }
173
- }, options.timeout || 30000);
175
+ }, options.timeout || 60000);
174
176
  const env = this.createEnv(testConfig, options);
175
177
  }
176
178
  afterAll(async () => {
@@ -215,8 +217,11 @@ class BasicCaseCreator {
215
217
  try {
216
218
  await runFn(fn);
217
219
  }
218
- catch (e) {
219
- throw new Error(`Error: ${description} failed\n${e.stack}`);
220
+ catch (err) {
221
+ const e = err;
222
+ const message = `Error: ${description} failed:\n${e.message}`;
223
+ e.message = message;
224
+ throw e;
220
225
  }
221
226
  for (const after of afterTasks) {
222
227
  await runFn(after);
@@ -237,7 +242,8 @@ class BasicCaseCreator {
237
242
  expect(typeof fn === "function");
238
243
  afterTasks.push(fn);
239
244
  },
240
- jest
245
+ jest: global.jest || global.rstest,
246
+ rstest: global.rstest
241
247
  };
242
248
  }
243
249
  createEnv(testConfig, options) {
@@ -255,7 +261,6 @@ class BasicCaseCreator {
255
261
  clean(folders) {
256
262
  for (const f of folders) {
257
263
  (0, rimraf_1.rimrafSync)(f);
258
- node_fs_1.default.mkdirSync(f, { recursive: true });
259
264
  }
260
265
  }
261
266
  skip(name, reason) {
@@ -10,6 +10,7 @@ export declare class Tester implements ITester {
10
10
  prepare(): Promise<void>;
11
11
  compile(): Promise<void>;
12
12
  check(env: ITestEnv): Promise<void>;
13
+ after(): Promise<void>;
13
14
  next(): boolean;
14
15
  resume(): Promise<void>;
15
16
  private runStepMethods;