@rspack/test-tools 1.6.0 → 1.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/case/common.js +2 -2
- package/dist/case/defaults.d.ts +1 -1
- package/dist/case/defaults.js +1 -1
- package/dist/case/diagnostic.js +3 -3
- package/dist/case/esm-output.js +1 -1
- package/dist/case/hash.js +5 -2
- package/dist/case/hook.js +1 -1
- package/dist/case/hot-step.js +4 -3
- package/dist/case/stats-output.js +1 -1
- package/dist/helper/directory.d.ts +1 -1
- package/dist/helper/expect/to-match-file-snapshot.d.ts +1 -1
- package/dist/helper/expect/to-match-file-snapshot.js +2 -2
- package/dist/helper/legacy/createLazyTestEnv.d.ts +3 -3
- package/dist/helper/legacy/createLazyTestEnv.js +2 -3
- package/dist/helper/setup-env.js +0 -4
- package/dist/helper/setup-expect.js +1 -1
- package/dist/helper/setup-wasm.js +2 -2
- package/dist/runner/node/index.d.ts +0 -1
- package/dist/runner/node/index.js +22 -54
- package/dist/runner/web/index.d.ts +4 -2
- package/dist/runner/web/index.js +61 -18
- package/dist/test/creator.js +4 -6
- package/dist/type.d.ts +4 -3
- package/dist/type.js +1 -1
- package/package.json +5 -8
- package/rstest.d.ts +24 -0
- package/dist/jest/ignore-snapshot-default-reporter.d.ts +0 -2
- package/dist/jest/ignore-snapshot-default-reporter.js +0 -57
- package/dist/jest/ignore-snapshot-summary-reporter.d.ts +0 -2
- package/dist/jest/ignore-snapshot-summary-reporter.js +0 -24
- package/dist/jest/patch-node-env.d.ts +0 -5
- package/dist/jest/patch-node-env.js +0 -18
- package/dist/jest/slash.d.ts +0 -2
- package/dist/jest/slash.js +0 -16
- package/jest.d.ts +0 -27
package/README.md
CHANGED
|
@@ -16,7 +16,7 @@ We expect to reuse the tests for Rspack wasm target as many as possible and we h
|
|
|
16
16
|
2. Set `maxWorkers` to `1`, `maxConcurrency` to `1` and disable concurrent mode to avoid flaky failures.
|
|
17
17
|
3. `forceExit` is needed.
|
|
18
18
|
|
|
19
|
-
Also check all the skipped testcases with `!process.env.WASM` in `test.filter.js`s and the skipped testsuits in `
|
|
19
|
+
Also check all the skipped testcases with `!process.env.WASM` in `test.filter.js`s and the skipped testsuits in `rstest.config.ts`s. They are divided into two categories:
|
|
20
20
|
|
|
21
21
|
1. Skip due to lacks of api support, such as tests related to swc wasm plugins, pnp and profiling. We skip them to avoid obsolete snapshot errors.
|
|
22
22
|
2. Skip temporarily and should be investigate in the future. There could be something wrong with test harness and rspack wasm itself. Since it could be time-consuming to figure out all of them so in this stage we use the wasm test ci to avoid the regression rather than improve its stability.
|
package/dist/case/common.js
CHANGED
|
@@ -132,7 +132,7 @@ async function check(env, context, name) {
|
|
|
132
132
|
}
|
|
133
133
|
async function checkSnapshot(env, context, name, snapshot, filter) {
|
|
134
134
|
if (path_1.default.extname(snapshot) === ".snap") {
|
|
135
|
-
throw new Error("Snapshot with `.snap` will be managed by
|
|
135
|
+
throw new Error("Snapshot with `.snap` will be managed by rstest, please use `.snap.txt` instead");
|
|
136
136
|
}
|
|
137
137
|
const compilerManager = context.getCompiler();
|
|
138
138
|
const stats = compilerManager.getStats();
|
|
@@ -176,7 +176,7 @@ async function checkSnapshot(env, context, name, snapshot, filter) {
|
|
|
176
176
|
const snapshotPath = path_1.default.isAbsolute(snapshot)
|
|
177
177
|
? snapshot
|
|
178
178
|
: path_1.default.resolve(context.getSource(), path_1.default.join("__snapshots__", `${snapshot}${total > 1 ? `-${i}` : ""}`));
|
|
179
|
-
env.expect(content).
|
|
179
|
+
env.expect(content).toMatchFileSnapshotSync(snapshotPath);
|
|
180
180
|
}
|
|
181
181
|
}
|
|
182
182
|
async function afterExecute(context, name) {
|
package/dist/case/defaults.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export declare function getRspackDefaultConfig(cwd: string, config: RspackOption
|
|
|
5
5
|
export type TDefaultsCaseConfig = {
|
|
6
6
|
options?: (context: ITestContext) => RspackOptions;
|
|
7
7
|
cwd?: string;
|
|
8
|
-
diff: (diff:
|
|
8
|
+
diff: (diff: Assertion<RspackTestDiff>, defaults: Assertion<RspackOptions>) => Promise<void>;
|
|
9
9
|
description: string;
|
|
10
10
|
};
|
|
11
11
|
declare class RspackTestDiff {
|
package/dist/case/defaults.js
CHANGED
|
@@ -88,7 +88,7 @@ async function run(name, processor) {
|
|
|
88
88
|
context.emitError(e);
|
|
89
89
|
}
|
|
90
90
|
finally {
|
|
91
|
-
await processor.check?.({ expect, it, beforeEach, afterEach,
|
|
91
|
+
await processor.check?.({ expect, it, beforeEach, afterEach, rstest }, context);
|
|
92
92
|
await processor.after?.(context);
|
|
93
93
|
}
|
|
94
94
|
}
|
package/dist/case/diagnostic.js
CHANGED
|
@@ -130,7 +130,7 @@ async function check(env, context, name, options) {
|
|
|
130
130
|
const errorOutputPath = node_path_1.default.resolve(context.getSource(options.snapshot));
|
|
131
131
|
const errorStatsOutputPath = node_path_1.default.resolve(context.getSource(options.snapshotErrors));
|
|
132
132
|
const warningStatsOutputPath = node_path_1.default.resolve(context.getSource(options.snapshotWarning));
|
|
133
|
-
env.expect(output).
|
|
134
|
-
env.expect(errors).
|
|
135
|
-
env.expect(warnings).
|
|
133
|
+
env.expect(output).toMatchFileSnapshotSync(errorOutputPath);
|
|
134
|
+
env.expect(errors).toMatchFileSnapshotSync(errorStatsOutputPath);
|
|
135
|
+
env.expect(warnings).toMatchFileSnapshotSync(warningStatsOutputPath);
|
|
136
136
|
}
|
package/dist/case/esm-output.js
CHANGED
package/dist/case/hash.js
CHANGED
|
@@ -72,8 +72,11 @@ async function check(env, context, name) {
|
|
|
72
72
|
const stats = compiler.getStats();
|
|
73
73
|
const testConfig = context.getTestConfig();
|
|
74
74
|
if (!stats) {
|
|
75
|
-
|
|
76
|
-
|
|
75
|
+
throw new Error("No stats found\n" +
|
|
76
|
+
context
|
|
77
|
+
.getError()
|
|
78
|
+
.map(e => e.stack)
|
|
79
|
+
.join("\n"));
|
|
77
80
|
}
|
|
78
81
|
if (REG_ERROR_CASE.test(name)) {
|
|
79
82
|
env.expect(stats.hasErrors());
|
package/dist/case/hook.js
CHANGED
|
@@ -189,7 +189,7 @@ class HookCasesContext extends context_1.TestContext {
|
|
|
189
189
|
}, "");
|
|
190
190
|
env
|
|
191
191
|
.expect(snapshots)
|
|
192
|
-
.
|
|
192
|
+
.toMatchFileSnapshotSync(node_path_1.default.join(this.src, "hooks.snap.txt"), options);
|
|
193
193
|
}
|
|
194
194
|
}
|
|
195
195
|
exports.HookCasesContext = HookCasesContext;
|
package/dist/case/hot-step.js
CHANGED
|
@@ -96,8 +96,9 @@ function createHotStepProcessor(name, src, temp, target) {
|
|
|
96
96
|
return str.split(raw).join(replacement);
|
|
97
97
|
}, str);
|
|
98
98
|
};
|
|
99
|
-
const
|
|
100
|
-
|
|
99
|
+
const assets = stats.assets.sort((a, b) => a.name.localeCompare(b.name));
|
|
100
|
+
const fileList = assets
|
|
101
|
+
.map(i => {
|
|
101
102
|
const fileName = i.name;
|
|
102
103
|
const renderName = replaceFileName(fileName);
|
|
103
104
|
const content = replaceContent(fs_extra_1.default.readFileSync(context.getDist(fileName), "utf-8"));
|
|
@@ -238,7 +239,7 @@ ${runtime.javascript.disposedModules.map(i => `- ${i}`).join("\n")}
|
|
|
238
239
|
return match.replace(capture, "PORT");
|
|
239
240
|
})
|
|
240
241
|
.trim();
|
|
241
|
-
env.expect(content).
|
|
242
|
+
env.expect(content).toMatchFileSnapshotSync(snapshotPath);
|
|
242
243
|
}
|
|
243
244
|
const originRun = processor.run;
|
|
244
245
|
processor.run = async function (env, context) {
|
|
@@ -180,7 +180,7 @@ async function check(env, context, name, writeStatsOuptut, snapshot, stderr) {
|
|
|
180
180
|
const snapshotPath = node_path_1.default.isAbsolute(snapshot)
|
|
181
181
|
? snapshot
|
|
182
182
|
: node_path_1.default.resolve(context.getSource(), `./__snapshots__/${snapshot}`);
|
|
183
|
-
env.expect(new RspackStats(actual)).
|
|
183
|
+
env.expect(new RspackStats(actual)).toMatchFileSnapshotSync(snapshotPath);
|
|
184
184
|
const testConfig = context.getTestConfig();
|
|
185
185
|
if (typeof testConfig?.validate === "function") {
|
|
186
186
|
testConfig.validate(stats, stderr.toString());
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* @param filepath Path to the file to match against
|
|
6
6
|
* @param options Additional options for matching
|
|
7
7
|
*/
|
|
8
|
-
export declare function
|
|
8
|
+
export declare function toMatchFileSnapshotSync(this: {
|
|
9
9
|
testPath: string;
|
|
10
10
|
currentTestName: string;
|
|
11
11
|
assertionCalls: number;
|
|
@@ -4,7 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
5
|
};
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.
|
|
7
|
+
exports.toMatchFileSnapshotSync = toMatchFileSnapshotSync;
|
|
8
8
|
/* istanbul ignore file */
|
|
9
9
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
10
10
|
const node_path_1 = __importDefault(require("node:path"));
|
|
@@ -29,7 +29,7 @@ const isEqual = (a, b) => {
|
|
|
29
29
|
* @param filepath Path to the file to match against
|
|
30
30
|
* @param options Additional options for matching
|
|
31
31
|
*/
|
|
32
|
-
function
|
|
32
|
+
function toMatchFileSnapshotSync(rawContent, filepath, options = {}) {
|
|
33
33
|
const content = Buffer.isBuffer(rawContent)
|
|
34
34
|
? rawContent
|
|
35
35
|
: serialize(rawContent, /* ident */ 2, {
|
|
@@ -4,8 +4,8 @@ declare function _exports(globalTimeout?: number, nameSuffix?: string): {
|
|
|
4
4
|
it(...args: any[]): void;
|
|
5
5
|
beforeEach(...args: any[]): void;
|
|
6
6
|
afterEach(...args: any[]): void;
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
rstest:
|
|
7
|
+
/** @type {import('@rstest/core').Expect} */
|
|
8
|
+
expect: import("@rstest/core").Expect;
|
|
9
|
+
rstest: import("@rstest/core", { with: { "resolution-mode": "import" } }).RstestUtilities;
|
|
10
10
|
};
|
|
11
11
|
export = _exports;
|
|
@@ -109,9 +109,8 @@ module.exports = (globalTimeout = 2000, nameSuffix = "") => {
|
|
|
109
109
|
fixAsyncError(currentDescribeBlock.hooks[currentDescribeBlock.hooks.length - 1]);
|
|
110
110
|
});
|
|
111
111
|
},
|
|
112
|
+
/** @type {import('@rstest/core').Expect} */
|
|
112
113
|
expect,
|
|
113
|
-
|
|
114
|
-
// Compatible with rstest
|
|
115
|
-
rstest: global.rstest || global.jest
|
|
114
|
+
rstest,
|
|
116
115
|
};
|
|
117
116
|
};
|
package/dist/helper/setup-env.js
CHANGED
|
@@ -18,10 +18,6 @@ if (process.env.RSTEST) {
|
|
|
18
18
|
global.__RSPACK_TEST_TOOLS_PATH__ ??= process.env.__RSPACK_TEST_TOOLS_PATH__;
|
|
19
19
|
global.__DEBUG__ ??= process.env.DEBUG === "test";
|
|
20
20
|
}
|
|
21
|
-
else {
|
|
22
|
-
// Compatible with wasm tests (lazyTestEnv)
|
|
23
|
-
global.rstest = jest;
|
|
24
|
-
}
|
|
25
21
|
if (process.env.ALTERNATIVE_SORT) {
|
|
26
22
|
const oldSort = Array.prototype.sort;
|
|
27
23
|
Array.prototype.sort = function (cmp) {
|
|
@@ -7,7 +7,7 @@ const serializers_1 = require("./serializers");
|
|
|
7
7
|
expect.extend({
|
|
8
8
|
// CHANGE: new test matcher for `rspack-test-tools`
|
|
9
9
|
// @ts-expect-error
|
|
10
|
-
|
|
10
|
+
toMatchFileSnapshotSync: to_match_file_snapshot_1.toMatchFileSnapshotSync,
|
|
11
11
|
toBeTypeOf: to_be_typeof_1.toBeTypeOf,
|
|
12
12
|
toEndWith: to_end_with_1.toEndWith
|
|
13
13
|
});
|
|
@@ -9,11 +9,11 @@ function toMatchSnapshot() {
|
|
|
9
9
|
function toMatchInlineSnapshot() {
|
|
10
10
|
return { pass: true, message: () => "" };
|
|
11
11
|
}
|
|
12
|
-
function
|
|
12
|
+
function toMatchFileSnapshotSync() {
|
|
13
13
|
return { pass: true, message: () => "" };
|
|
14
14
|
}
|
|
15
15
|
expect.extend({
|
|
16
16
|
toMatchSnapshot,
|
|
17
17
|
toMatchInlineSnapshot,
|
|
18
|
-
|
|
18
|
+
toMatchFileSnapshotSync
|
|
19
19
|
});
|
|
@@ -39,4 +39,3 @@ export declare class NodeRunner implements ITestRunner {
|
|
|
39
39
|
protected createCjsRequirer(): TRunnerRequirer;
|
|
40
40
|
protected createEsmRequirer(): TRunnerRequirer;
|
|
41
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.
|
|
39
|
+
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,7 +45,6 @@ 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+)/;
|
|
49
48
|
const isRelativePath = (p) => /^\.\.?\//.test(p);
|
|
50
49
|
const getSubPath = (p) => {
|
|
51
50
|
const lastSlash = p.lastIndexOf("/");
|
|
@@ -179,6 +178,7 @@ class NodeRunner {
|
|
|
179
178
|
Buffer,
|
|
180
179
|
setImmediate,
|
|
181
180
|
self: this.globalContext,
|
|
181
|
+
__TEST_PATH__: __TEST_PATH__,
|
|
182
182
|
__MODE__: this._options.compilerOptions.mode,
|
|
183
183
|
__SNAPSHOT__: node_path_1.default.join(this._options.source, "__snapshot__"),
|
|
184
184
|
Worker: (0, createFakeWorker_1.default)(this._options.env, {
|
|
@@ -347,37 +347,31 @@ class NodeRunner {
|
|
|
347
347
|
currentModuleScope.__STATS_I__ = statsIndex;
|
|
348
348
|
}
|
|
349
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;
|
|
364
350
|
const args = Object.keys(currentModuleScope);
|
|
365
351
|
const argValues = args.map(arg => currentModuleScope[arg]);
|
|
366
352
|
const code = `(function(${args.join(", ")}) {
|
|
367
|
-
|
|
368
|
-
${file.content}
|
|
369
|
-
} catch(err) {
|
|
370
|
-
throw __CREATE_LOCATED_ERROR__(err, __FILE__);
|
|
371
|
-
}
|
|
353
|
+
${file.content}
|
|
372
354
|
})`;
|
|
373
355
|
this.preExecute(code, file);
|
|
374
356
|
this.log(`run mode: ${this._options.runInNewContext ? "new context" : "this context"}`);
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
357
|
+
try {
|
|
358
|
+
const fn = this._options.runInNewContext
|
|
359
|
+
? node_vm_1.default.runInNewContext(code, this.globalContext, {
|
|
360
|
+
filename: file.path,
|
|
361
|
+
lineOffset: -1
|
|
362
|
+
})
|
|
363
|
+
: node_vm_1.default.runInThisContext(code, {
|
|
364
|
+
filename: file.path,
|
|
365
|
+
lineOffset: -1
|
|
366
|
+
});
|
|
367
|
+
fn.call(this._options.testConfig.nonEsmThis
|
|
368
|
+
? this._options.testConfig.nonEsmThis(modulePath)
|
|
369
|
+
: m.exports, ...argValues);
|
|
370
|
+
}
|
|
371
|
+
catch (e) {
|
|
372
|
+
this._options.errors?.push(e);
|
|
373
|
+
throw e;
|
|
374
|
+
}
|
|
381
375
|
this.postExecute(m, file);
|
|
382
376
|
this.log(`end cjs: ${modulePath}`);
|
|
383
377
|
return m.exports;
|
|
@@ -391,7 +385,7 @@ class NodeRunner {
|
|
|
391
385
|
const esmIdentifier = this._options.name;
|
|
392
386
|
return (currentDirectory, modulePath, context = {}) => {
|
|
393
387
|
if (!node_vm_1.SourceTextModule) {
|
|
394
|
-
throw new Error("Running this test requires '--experimental-vm-modules'.\nRun with 'node --experimental-vm-modules node_modules/
|
|
388
|
+
throw new Error("Running this test requires '--experimental-vm-modules'.\nRun with 'node --experimental-vm-modules node_modules/@rstest/core/bin/rstest'.");
|
|
395
389
|
}
|
|
396
390
|
const _require = this.getRequire();
|
|
397
391
|
const file = context.file || this.getFile(modulePath, currentDirectory);
|
|
@@ -454,29 +448,3 @@ class NodeRunner {
|
|
|
454
448
|
}
|
|
455
449
|
}
|
|
456
450
|
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;
|
|
@@ -11,7 +11,7 @@ export declare class WebRunner extends NodeRunner {
|
|
|
11
11
|
getGlobal(name: string): unknown;
|
|
12
12
|
protected log(message: string): void;
|
|
13
13
|
protected createResourceLoader(): {
|
|
14
|
-
fetch(url: string,
|
|
14
|
+
fetch(url: string, options: {
|
|
15
15
|
element: HTMLScriptElement;
|
|
16
16
|
}): any;
|
|
17
17
|
};
|
|
@@ -21,8 +21,10 @@ export declare class WebRunner extends NodeRunner {
|
|
|
21
21
|
{
|
|
22
22
|
exports: Record<string, unknown>;
|
|
23
23
|
},
|
|
24
|
-
string
|
|
24
|
+
string,
|
|
25
|
+
number
|
|
25
26
|
];
|
|
26
27
|
protected createJSDOMRequirer(): TRunnerRequirer;
|
|
27
28
|
protected createRunner(): void;
|
|
28
29
|
}
|
|
30
|
+
export declare const createLocatedError: (collectedErrors: Error[], offset: number) => (e: Error, file: TRunnerFile) => Error;
|
package/dist/runner/web/index.js
CHANGED
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.WebRunner = void 0;
|
|
6
|
+
exports.createLocatedError = exports.WebRunner = void 0;
|
|
7
7
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
8
8
|
const node_path_1 = __importDefault(require("node:path"));
|
|
9
9
|
const node_url_1 = require("node:url");
|
|
@@ -90,7 +90,18 @@ class WebRunner extends node_1.NodeRunner {
|
|
|
90
90
|
createResourceLoader() {
|
|
91
91
|
const that = this;
|
|
92
92
|
class CustomResourceLoader extends jsdom_1.ResourceLoader {
|
|
93
|
-
fetch(url,
|
|
93
|
+
fetch(url, options) {
|
|
94
|
+
if (that._options.testConfig.resourceLoader) {
|
|
95
|
+
that.log(`resource custom loader: start ${url}`);
|
|
96
|
+
const content = that._options.testConfig.resourceLoader(url, options.element);
|
|
97
|
+
if (content !== undefined) {
|
|
98
|
+
that.log(`resource custom loader: accepted`);
|
|
99
|
+
return Promise.resolve(content);
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
that.log(`resource custom loader: not found`);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
94
105
|
const filePath = that.urlToPath(url);
|
|
95
106
|
that.log(`resource loader: ${url} -> ${filePath}`);
|
|
96
107
|
let finalCode;
|
|
@@ -234,15 +245,16 @@ class WebRunner extends node_1.NodeRunner {
|
|
|
234
245
|
return Reflect.set(target, prop, value, receiver);
|
|
235
246
|
}
|
|
236
247
|
});`;
|
|
237
|
-
const
|
|
248
|
+
const proxyLines = proxyCode.split("\n");
|
|
249
|
+
const locatedError = (0, exports.createLocatedError)(this._options.errors || [], proxyLines.length + 1);
|
|
238
250
|
const originIt = currentModuleScope.it;
|
|
239
251
|
currentModuleScope.it = (description, fn) => {
|
|
240
|
-
originIt(description, async () => {
|
|
252
|
+
return originIt(description, async (...args) => {
|
|
241
253
|
try {
|
|
242
|
-
await fn();
|
|
254
|
+
return await fn(...args);
|
|
243
255
|
}
|
|
244
|
-
catch (
|
|
245
|
-
throw
|
|
256
|
+
catch (e) {
|
|
257
|
+
throw locatedError(e, file);
|
|
246
258
|
}
|
|
247
259
|
});
|
|
248
260
|
};
|
|
@@ -253,18 +265,17 @@ class WebRunner extends node_1.NodeRunner {
|
|
|
253
265
|
.join(", ");
|
|
254
266
|
this.dom.window[scopeKey] = currentModuleScope;
|
|
255
267
|
this.dom.window["__GLOBAL_SHARED__"] = this.globalContext;
|
|
268
|
+
this.dom.window["__LOCATED_ERROR__"] = locatedError;
|
|
256
269
|
this.dom.window["__FILE__"] = file;
|
|
257
|
-
this.dom.window["__CREATE_LOCATED_ERROR__"] = createJSDOMLocatedError;
|
|
258
270
|
return [
|
|
259
271
|
m,
|
|
260
272
|
`${proxyCode}
|
|
261
|
-
(function(window, self, globalThis, console, ${args.join(", ")}) {
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
})($$g$$, $$self$$, $$g$$, window["console"], ${argValues});`
|
|
273
|
+
(function(window, self, globalThis, console, ${args.join(", ")}) { try {
|
|
274
|
+
${file.content}
|
|
275
|
+
} catch (e) {
|
|
276
|
+
throw __LOCATED_ERROR__(e, window["__FILE__"]);
|
|
277
|
+
}})($$g$$, $$self$$, $$g$$, window["console"], ${argValues});`,
|
|
278
|
+
proxyLines.length + 1
|
|
268
279
|
];
|
|
269
280
|
}
|
|
270
281
|
createJSDOMRequirer() {
|
|
@@ -277,15 +288,21 @@ class WebRunner extends node_1.NodeRunner {
|
|
|
277
288
|
if (file.path in this.requireCache) {
|
|
278
289
|
return this.requireCache[file.path].exports;
|
|
279
290
|
}
|
|
280
|
-
const [m, code] = this.getModuleContent(file);
|
|
291
|
+
const [m, code, lineOffset] = this.getModuleContent(file);
|
|
281
292
|
this.preExecute(code, file);
|
|
282
293
|
try {
|
|
283
294
|
const script = new node_vm_1.Script(code);
|
|
284
295
|
const vmContext = this.dom.getInternalVMContext();
|
|
285
|
-
script.runInContext(vmContext
|
|
296
|
+
script.runInContext(vmContext, {
|
|
297
|
+
filename: file.path,
|
|
298
|
+
lineOffset: -lineOffset
|
|
299
|
+
});
|
|
286
300
|
}
|
|
287
301
|
catch (e) {
|
|
288
|
-
|
|
302
|
+
const error = new Error(`Parse script '${file.path}' failed:\n${e.message}`);
|
|
303
|
+
error.stack = `${error.message}\n${e.stack}`;
|
|
304
|
+
this._options.errors?.push(error);
|
|
305
|
+
throw error;
|
|
289
306
|
}
|
|
290
307
|
this.postExecute(m, file);
|
|
291
308
|
this.requireCache[file.path] = m;
|
|
@@ -298,3 +315,29 @@ class WebRunner extends node_1.NodeRunner {
|
|
|
298
315
|
}
|
|
299
316
|
}
|
|
300
317
|
exports.WebRunner = WebRunner;
|
|
318
|
+
const createLocatedError = (collectedErrors, offset) => {
|
|
319
|
+
return (e, file) => {
|
|
320
|
+
const match = (e.stack || e.message).match(/<anonymous>:(\d+)/);
|
|
321
|
+
if (match) {
|
|
322
|
+
const [, line] = match;
|
|
323
|
+
const realLine = Number(line) - offset;
|
|
324
|
+
const codeLines = file.content.split("\n");
|
|
325
|
+
const lineContents = [
|
|
326
|
+
...codeLines
|
|
327
|
+
.slice(Math.max(0, realLine - 3), Math.max(0, realLine - 1))
|
|
328
|
+
.map(line => `│ ${line}`),
|
|
329
|
+
`│> ${codeLines[realLine - 1]}`,
|
|
330
|
+
...codeLines.slice(realLine, realLine + 2).map(line => `│ ${line}`)
|
|
331
|
+
];
|
|
332
|
+
const message = `Error in JSDOM when running file '${file.path}' at line ${realLine}: ${e.message}\n${lineContents.join("\n")}`;
|
|
333
|
+
const finalError = new Error(message);
|
|
334
|
+
finalError.stack = `${message}\n${e.stack}`;
|
|
335
|
+
collectedErrors.push(finalError);
|
|
336
|
+
return finalError;
|
|
337
|
+
}
|
|
338
|
+
else {
|
|
339
|
+
return e;
|
|
340
|
+
}
|
|
341
|
+
};
|
|
342
|
+
};
|
|
343
|
+
exports.createLocatedError = createLocatedError;
|
package/dist/test/creator.js
CHANGED
|
@@ -9,7 +9,7 @@ const node_path_1 = __importDefault(require("node:path"));
|
|
|
9
9
|
const rimraf_1 = require("rimraf");
|
|
10
10
|
const createLazyTestEnv_1 = __importDefault(require("../helper/legacy/createLazyTestEnv"));
|
|
11
11
|
const tester_1 = require("./tester");
|
|
12
|
-
const DEFAULT_MAX_CONCURRENT = 5;
|
|
12
|
+
const DEFAULT_MAX_CONCURRENT = process.env.WASM ? 1 : 5;
|
|
13
13
|
class BasicCaseCreator {
|
|
14
14
|
constructor(_options) {
|
|
15
15
|
this._options = _options;
|
|
@@ -36,7 +36,7 @@ class BasicCaseCreator {
|
|
|
36
36
|
const run = this.shouldRun(name);
|
|
37
37
|
const tester = this.createTester(name, src, dist, temp, testConfig, options);
|
|
38
38
|
const concurrent = process.env.WASM
|
|
39
|
-
?
|
|
39
|
+
? 1
|
|
40
40
|
: testConfig.concurrent || options.concurrent;
|
|
41
41
|
if (options.describe) {
|
|
42
42
|
if (run) {
|
|
@@ -242,8 +242,7 @@ class BasicCaseCreator {
|
|
|
242
242
|
expect(typeof fn === "function");
|
|
243
243
|
afterTasks.push(fn);
|
|
244
244
|
},
|
|
245
|
-
|
|
246
|
-
rstest: global.rstest
|
|
245
|
+
rstest
|
|
247
246
|
};
|
|
248
247
|
}
|
|
249
248
|
createEnv(testConfig, options) {
|
|
@@ -255,8 +254,7 @@ class BasicCaseCreator {
|
|
|
255
254
|
it,
|
|
256
255
|
beforeEach,
|
|
257
256
|
afterEach,
|
|
258
|
-
|
|
259
|
-
rstest: global.rstest
|
|
257
|
+
rstest
|
|
260
258
|
};
|
|
261
259
|
}
|
|
262
260
|
clean(folders) {
|
package/dist/type.d.ts
CHANGED
|
@@ -108,10 +108,10 @@ export type TDiffStatsItem = {
|
|
|
108
108
|
};
|
|
109
109
|
export type TDiffStats = {
|
|
110
110
|
root: string;
|
|
111
|
-
data:
|
|
111
|
+
data: TDiffStatsItem[];
|
|
112
112
|
};
|
|
113
113
|
export interface ITestEnv {
|
|
114
|
-
expect:
|
|
114
|
+
expect: Expect;
|
|
115
115
|
it: (...args: any[]) => void;
|
|
116
116
|
beforeEach: (...args: any[]) => void;
|
|
117
117
|
afterEach: (...args: any[]) => void;
|
|
@@ -139,6 +139,7 @@ export type TTestConfig = {
|
|
|
139
139
|
esmLibPluginOptions?: {
|
|
140
140
|
preserveModules?: string;
|
|
141
141
|
};
|
|
142
|
+
resourceLoader?: (url: string, element: HTMLScriptElement) => Buffer | null;
|
|
142
143
|
};
|
|
143
144
|
export type TTestFilter = (creatorConfig: Record<string, unknown>, testConfig: TTestConfig) => boolean | string;
|
|
144
145
|
export interface ITestRunner {
|
|
@@ -171,7 +172,7 @@ export declare enum EEsmMode {
|
|
|
171
172
|
}
|
|
172
173
|
export interface IModuleScope extends ITestEnv {
|
|
173
174
|
console: Record<string, (...args: any[]) => void>;
|
|
174
|
-
expect:
|
|
175
|
+
expect: Expect;
|
|
175
176
|
[key: string]: any;
|
|
176
177
|
}
|
|
177
178
|
export interface IGlobalContext {
|
package/dist/type.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rspack/test-tools",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.2",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Test tools for rspack",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -15,14 +15,13 @@
|
|
|
15
15
|
"./package.json": "./package.json",
|
|
16
16
|
"./helper/*": "./dist/helper/*.js",
|
|
17
17
|
"./helper/legacy/*": "./dist/helper/legacy/*.js",
|
|
18
|
-
"./helper/util/*": "./dist/helper/util/*.js"
|
|
19
|
-
"./jest/*": "./dist/jest/*.js"
|
|
18
|
+
"./helper/util/*": "./dist/helper/util/*.js"
|
|
20
19
|
},
|
|
21
20
|
"files": [
|
|
22
21
|
"client",
|
|
23
22
|
"dist",
|
|
24
23
|
"template",
|
|
25
|
-
"
|
|
24
|
+
"rstest.d.ts"
|
|
26
25
|
],
|
|
27
26
|
"publishConfig": {
|
|
28
27
|
"access": "public",
|
|
@@ -40,15 +39,13 @@
|
|
|
40
39
|
"@babel/parser": "7.28.5",
|
|
41
40
|
"@babel/traverse": "7.28.5",
|
|
42
41
|
"@babel/types": "7.28.5",
|
|
43
|
-
"@jest/reporters": "29.7.0",
|
|
44
42
|
"cross-env": "^10.1.0",
|
|
45
43
|
"filenamify": "4.3.0",
|
|
46
44
|
"fs-extra": "^11.3.2",
|
|
47
|
-
"iconv-lite": "^0.
|
|
45
|
+
"iconv-lite": "^0.7.0",
|
|
48
46
|
"javascript-stringify": "^2.1.0",
|
|
49
47
|
"jest-diff": "^29.7.0",
|
|
50
48
|
"jest-snapshot": "29.7.0",
|
|
51
|
-
"jest-environment-node": "29.7.0",
|
|
52
49
|
"jsdom": "^26.1.0",
|
|
53
50
|
"memfs": "4.48.1",
|
|
54
51
|
"path-serializer": "0.5.1",
|
|
@@ -68,7 +65,7 @@
|
|
|
68
65
|
"@types/jsdom": "^21.1.7",
|
|
69
66
|
"typescript": "^5.9.3",
|
|
70
67
|
"wast-loader": "^1.14.1",
|
|
71
|
-
"@rspack/core": "1.6.
|
|
68
|
+
"@rspack/core": "1.6.2"
|
|
72
69
|
},
|
|
73
70
|
"peerDependencies": {
|
|
74
71
|
"@rspack/core": ">=1.0.0"
|
package/rstest.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/// <reference types="@rstest/core/globals" />
|
|
2
|
+
|
|
3
|
+
import type { DiffOptions } from "jest-diff";
|
|
4
|
+
|
|
5
|
+
declare interface FileMatcherOptions {
|
|
6
|
+
diff?: DiffOptions;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
declare module "@rstest/core" {
|
|
10
|
+
interface Assertion {
|
|
11
|
+
toMatchFileSnapshotSync: (
|
|
12
|
+
filename?: string,
|
|
13
|
+
options?: FileMatcherOptions
|
|
14
|
+
) => void;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
declare global {
|
|
19
|
+
type Expect = import("@rstest/core").Expect;
|
|
20
|
+
type Describe = import("@rstest/core").Describe;
|
|
21
|
+
type Assertion<T> = import("@rstest/core").Assertion<T>;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export {};
|
|
@@ -1,57 +0,0 @@
|
|
|
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
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
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
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
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;
|
package/dist/jest/slash.d.ts
DELETED
package/dist/jest/slash.js
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
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
|
-
};
|
package/jest.d.ts
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
/// <reference types="jest" />
|
|
2
|
-
|
|
3
|
-
import type { DiffOptions } from "jest-diff";
|
|
4
|
-
|
|
5
|
-
declare interface FileMatcherOptions {
|
|
6
|
-
diff?: DiffOptions;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
declare global {
|
|
10
|
-
namespace jest {
|
|
11
|
-
interface Matchers<R, T> {
|
|
12
|
-
toMatchFileSnapshot: (
|
|
13
|
-
filename?: string,
|
|
14
|
-
options?: FileMatcherOptions
|
|
15
|
-
) => void;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
interface Expect {
|
|
19
|
-
toMatchFileSnapshot: (
|
|
20
|
-
filename?: string,
|
|
21
|
-
options?: FileMatcherOptions
|
|
22
|
-
) => void;
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
var rstest = jest;
|
|
27
|
-
}
|