@rspack-canary/test-tools 1.5.7-canary-a3406c0a-20250922173625 → 1.5.8-canary-6c1a40e3-20250925175235

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 (89) hide show
  1. package/dist/case/builtin.d.ts +2 -2
  2. package/dist/case/builtin.js +37 -28
  3. package/dist/case/cache.d.ts +1 -1
  4. package/dist/case/cache.js +135 -42
  5. package/dist/case/common.d.ts +10 -0
  6. package/dist/case/common.js +237 -0
  7. package/dist/case/compiler.d.ts +7 -4
  8. package/dist/case/compiler.js +144 -109
  9. package/dist/case/config.d.ts +3 -2
  10. package/dist/case/config.js +47 -39
  11. package/dist/case/defaults.d.ts +2 -2
  12. package/dist/case/defaults.js +28 -18
  13. package/dist/case/diagnostic.d.ts +1 -1
  14. package/dist/case/diagnostic.js +52 -43
  15. package/dist/case/diff.d.ts +17 -1
  16. package/dist/case/diff.js +170 -22
  17. package/dist/case/error.d.ts +14 -4
  18. package/dist/case/error.js +51 -21
  19. package/dist/case/hash.d.ts +1 -1
  20. package/dist/case/hash.js +41 -34
  21. package/dist/case/hook.d.ts +4 -5
  22. package/dist/case/hook.js +78 -70
  23. package/dist/case/hot-step.d.ts +1 -1
  24. package/dist/case/hot-step.js +9 -5
  25. package/dist/case/hot.d.ts +5 -5
  26. package/dist/case/hot.js +142 -55
  27. package/dist/case/incremental.d.ts +1 -1
  28. package/dist/case/incremental.js +19 -34
  29. package/dist/case/native-watcher.js +10 -23
  30. package/dist/case/normal.js +46 -31
  31. package/dist/case/runner.d.ts +18 -0
  32. package/dist/case/runner.js +108 -0
  33. package/dist/case/serial.d.ts +1 -1
  34. package/dist/case/serial.js +7 -15
  35. package/dist/case/stats-api.js +52 -22
  36. package/dist/case/stats-output.js +133 -137
  37. package/dist/case/treeshaking.js +33 -22
  38. package/dist/case/watch.d.ts +27 -0
  39. package/dist/case/watch.js +321 -21
  40. package/dist/index.d.ts +0 -2
  41. package/dist/index.js +0 -2
  42. package/dist/runner/index.d.ts +2 -7
  43. package/dist/runner/index.js +2 -7
  44. package/dist/runner/{runner/node → node}/index.d.ts +1 -2
  45. package/dist/runner/{runner/node → node}/index.js +2 -2
  46. package/dist/runner/{runner/web → web}/fake.d.ts +1 -2
  47. package/dist/runner/{runner/web → web}/fake.js +7 -7
  48. package/dist/runner/{runner/web → web}/index.d.ts +2 -2
  49. package/dist/runner/{runner/web → web}/index.js +1 -1
  50. package/dist/runner/{runner/web → web}/jsdom.d.ts +1 -2
  51. package/dist/runner/{runner/web → web}/jsdom.js +4 -4
  52. package/dist/test/context.d.ts +3 -5
  53. package/dist/test/context.js +22 -12
  54. package/dist/test/creator.d.ts +13 -12
  55. package/dist/test/creator.js +52 -43
  56. package/dist/test/tester.js +4 -1
  57. package/dist/type.d.ts +41 -10
  58. package/dist/type.js +7 -1
  59. package/package.json +6 -6
  60. package/dist/processor/basic.d.ts +0 -27
  61. package/dist/processor/basic.js +0 -157
  62. package/dist/processor/diff.d.ts +0 -30
  63. package/dist/processor/diff.js +0 -140
  64. package/dist/processor/index.d.ts +0 -6
  65. package/dist/processor/index.js +0 -22
  66. package/dist/processor/multi.d.ts +0 -19
  67. package/dist/processor/multi.js +0 -75
  68. package/dist/processor/simple.d.ts +0 -24
  69. package/dist/processor/simple.js +0 -51
  70. package/dist/processor/snapshot.d.ts +0 -12
  71. package/dist/processor/snapshot.js +0 -67
  72. package/dist/processor/watch.d.ts +0 -30
  73. package/dist/processor/watch.js +0 -252
  74. package/dist/runner/basic.d.ts +0 -10
  75. package/dist/runner/basic.js +0 -64
  76. package/dist/runner/cache.d.ts +0 -5
  77. package/dist/runner/cache.js +0 -92
  78. package/dist/runner/hot.d.ts +0 -5
  79. package/dist/runner/hot.js +0 -91
  80. package/dist/runner/multiple.d.ts +0 -11
  81. package/dist/runner/multiple.js +0 -52
  82. package/dist/runner/runner/index.d.ts +0 -2
  83. package/dist/runner/runner/index.js +0 -18
  84. package/dist/runner/type.d.ts +0 -42
  85. package/dist/runner/type.js +0 -9
  86. package/dist/runner/watch.d.ts +0 -7
  87. package/dist/runner/watch.js +0 -71
  88. package/dist/test/simple.d.ts +0 -5
  89. package/dist/test/simple.js +0 -43
@@ -1,3 +1,3 @@
1
- import { ECompilerType, type ITestContext, type TCompilerOptions } from "../type";
2
- export declare function defaultOptions<T extends ECompilerType.Rspack>(context: ITestContext): TCompilerOptions<T>;
1
+ import type { ECompilerType, ITestContext, TCompilerOptions } from "../type";
3
2
  export declare function createBuiltinCase(name: string, src: string, dist: string): void;
3
+ export declare function defaultOptions<T extends ECompilerType.Rspack>(context: ITestContext): TCompilerOptions<T>;
@@ -3,16 +3,50 @@ 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.defaultOptions = defaultOptions;
7
6
  exports.createBuiltinCase = createBuiltinCase;
7
+ exports.defaultOptions = defaultOptions;
8
8
  const node_path_1 = __importDefault(require("node:path"));
9
9
  const core_1 = require("@rspack/core");
10
10
  const fs_extra_1 = __importDefault(require("fs-extra"));
11
11
  const webpack_merge_1 = require("webpack-merge");
12
12
  const helper_1 = require("../helper");
13
- const processor_1 = require("../processor");
14
13
  const creator_1 = require("../test/creator");
15
- const type_1 = require("../type");
14
+ const common_1 = require("./common");
15
+ const creator = new creator_1.BasicCaseCreator({
16
+ clean: true,
17
+ describe: false,
18
+ description(name) {
19
+ return `${name} should match snapshot`;
20
+ },
21
+ steps: ({ name, src }) => {
22
+ const cat = node_path_1.default.basename(node_path_1.default.dirname(src));
23
+ const filter = FILTERS[cat];
24
+ return [
25
+ {
26
+ config: async (context) => {
27
+ const compiler = (0, common_1.getCompiler)(context, name);
28
+ compiler.setOptions(defaultOptions(context));
29
+ },
30
+ compiler: async (context) => {
31
+ await (0, common_1.compiler)(context, name);
32
+ },
33
+ build: async (context) => {
34
+ await (0, common_1.build)(context, name);
35
+ },
36
+ run: async (env, context) => {
37
+ // no need to run, just check snapshot
38
+ },
39
+ check: async (env, context) => {
40
+ await (0, common_1.checkSnapshot)(env, context, name, "output.snap.txt", filter);
41
+ }
42
+ }
43
+ ];
44
+ },
45
+ concurrent: true
46
+ });
47
+ function createBuiltinCase(name, src, dist) {
48
+ creator.create(name, src, dist);
49
+ }
16
50
  function defaultOptions(context) {
17
51
  let defaultOptions = {
18
52
  entry: {
@@ -163,28 +197,3 @@ const FILTERS = {
163
197
  "plugin-css-modules": (file) => file.endsWith(".css") || ((0, helper_1.isJavaScript)(file) && !file.includes("runtime")),
164
198
  "plugin-html": (file) => file.endsWith(".html")
165
199
  };
166
- const creator = new creator_1.BasicCaseCreator({
167
- clean: true,
168
- describe: false,
169
- description(name) {
170
- return `${name} should match snapshot`;
171
- },
172
- steps: ({ name, src }) => {
173
- const cat = node_path_1.default.basename(node_path_1.default.dirname(src));
174
- const filter = FILTERS[cat];
175
- return [
176
- new processor_1.SnapshotProcessor({
177
- name,
178
- snapshot: "output.snap.txt",
179
- snapshotFileFilter: filter,
180
- compilerType: type_1.ECompilerType.Rspack,
181
- defaultOptions,
182
- runable: false
183
- })
184
- ];
185
- },
186
- concurrent: true
187
- });
188
- function createBuiltinCase(name, src, dist) {
189
- creator.create(name, src, dist);
190
- }
@@ -1,2 +1,2 @@
1
- import { ECompilerType, type TCompilerOptions } from "../type";
1
+ import { type ECompilerType, type TCompilerOptions } from "../type";
2
2
  export declare function createCacheCase(name: string, src: string, dist: string, target: TCompilerOptions<ECompilerType.Rspack>["target"], temp: string): void;
@@ -8,10 +8,70 @@ const node_path_1 = __importDefault(require("node:path"));
8
8
  const core_1 = __importDefault(require("@rspack/core"));
9
9
  const helper_1 = require("../helper");
10
10
  const hot_update_1 = require("../helper/hot-update");
11
- const processor_1 = require("../processor");
11
+ const checkArrayExpectation_1 = __importDefault(require("../helper/legacy/checkArrayExpectation"));
12
12
  const runner_1 = require("../runner");
13
13
  const creator_1 = require("../test/creator");
14
14
  const type_1 = require("../type");
15
+ const common_1 = require("./common");
16
+ const runner_2 = require("./runner");
17
+ const MAX_COMPILER_INDEX = 100;
18
+ function createCacheProcessor(name, src, temp, target) {
19
+ const updatePlugin = new hot_update_1.HotUpdatePlugin(src, temp);
20
+ return {
21
+ before: async (context) => {
22
+ await updatePlugin.initialize();
23
+ context.setValue(name, "hotUpdateContext", updatePlugin);
24
+ },
25
+ config: async (context) => {
26
+ const compiler = (0, common_1.getCompiler)(context, name);
27
+ let options = defaultOptions(context, temp, target);
28
+ options = await (0, common_1.config)(context, name, ["rspack.config.js", "webpack.config.js"].map(i => node_path_1.default.resolve(temp, i)), options);
29
+ overrideOptions(options, temp, target, updatePlugin);
30
+ compiler.setOptions(options);
31
+ },
32
+ compiler: async (context) => {
33
+ await (0, common_1.compiler)(context, name);
34
+ },
35
+ build: async (context) => {
36
+ await (0, common_1.build)(context, name);
37
+ },
38
+ run: async (env, context) => {
39
+ await (0, common_1.run)(env, context, name, context => findBundle(name, target, context));
40
+ },
41
+ check: async (env, context) => {
42
+ await (0, common_1.check)(env, context, name);
43
+ },
44
+ afterAll: async (context) => {
45
+ const updateIndex = updatePlugin.getUpdateIndex();
46
+ const totalUpdates = updatePlugin.getTotalUpdates();
47
+ if (updateIndex + 1 !== totalUpdates) {
48
+ throw new Error(`Should run all hot steps (${updateIndex + 1} / ${totalUpdates}): ${name}`);
49
+ }
50
+ }
51
+ };
52
+ }
53
+ function getCreator(target) {
54
+ if (!creators.has(target)) {
55
+ creators.set(target, new creator_1.BasicCaseCreator({
56
+ clean: true,
57
+ describe: true,
58
+ target,
59
+ steps: ({ name, src, target, temp }) => [
60
+ createCacheProcessor(name, src, temp, target)
61
+ ],
62
+ runner: {
63
+ key: (context, name, file) => name,
64
+ runner: createRunner
65
+ },
66
+ concurrent: true
67
+ }));
68
+ }
69
+ return creators.get(target);
70
+ }
71
+ function createCacheCase(name, src, dist, target, temp) {
72
+ const creator = getCreator(target);
73
+ creator.create(name, src, dist, temp);
74
+ }
15
75
  const creators = new Map();
16
76
  function defaultOptions(context, temp, target) {
17
77
  const options = {
@@ -70,7 +130,7 @@ function overrideOptions(options, temp, target, updatePlugin) {
70
130
  function findBundle(name, target, context) {
71
131
  const files = [];
72
132
  const prefiles = [];
73
- const compiler = context.getCompiler(name);
133
+ const compiler = (0, common_1.getCompiler)(context, name);
74
134
  if (!compiler)
75
135
  throw new Error("Compiler should exists when find bundle");
76
136
  const stats = compiler.getStats();
@@ -93,48 +153,81 @@ function findBundle(name, target, context) {
93
153
  }
94
154
  return [...prefiles, ...files];
95
155
  }
96
- function createCacheProcessor(name, src, temp, target) {
97
- const updatePlugin = new hot_update_1.HotUpdatePlugin(src, temp);
98
- const processor = new processor_1.BasicProcessor({
99
- name,
100
- runable: true,
101
- compilerType: type_1.ECompilerType.Rspack,
102
- configFiles: ["rspack.config.js", "webpack.config.js"].map(i => node_path_1.default.resolve(temp, i)),
103
- defaultOptions: context => defaultOptions(context, temp, target),
104
- overrideOptions: (context, options) => overrideOptions(options, temp, target, updatePlugin),
105
- findBundle: context => findBundle(name, target, context)
106
- });
107
- processor.before = async (context) => {
108
- await updatePlugin.initialize();
109
- context.setValue(name, "hotUpdateContext", updatePlugin);
156
+ function createRunner(context, name, file, env) {
157
+ const compiler = context.getCompiler(name);
158
+ const options = compiler.getOptions();
159
+ let compilerIndex = 0;
160
+ const testConfig = context.getTestConfig();
161
+ const source = context.getSource();
162
+ const dist = context.getDist();
163
+ const updatePlugin = context.getValue(name, "hotUpdateContext");
164
+ const getWebRunner = () => {
165
+ return new runner_1.WebRunner({
166
+ dom: context.getValue(name, "documentType") || type_1.EDocumentType.JSDOM,
167
+ env,
168
+ stats: (0, runner_2.cachedStats)(context, name),
169
+ cachable: false,
170
+ name: name,
171
+ runInNewContext: false,
172
+ testConfig: {
173
+ ...testConfig,
174
+ moduleScope(ms, stats, options) {
175
+ const moduleScope = typeof testConfig.moduleScope === "function"
176
+ ? testConfig.moduleScope(ms, stats, options)
177
+ : ms;
178
+ moduleScope.COMPILER_INDEX = compilerIndex;
179
+ moduleScope.NEXT_HMR = nextHmr;
180
+ moduleScope.NEXT_START = nextStart;
181
+ return moduleScope;
182
+ }
183
+ },
184
+ source,
185
+ dist,
186
+ compilerOptions: options
187
+ });
110
188
  };
111
- const originalAfterAll = processor.afterAll;
112
- processor.afterAll = async function (context) {
113
- await originalAfterAll.call(this, context);
189
+ const nextHmr = async (m, options) => {
190
+ await updatePlugin.goNext();
191
+ const stats = await compiler.build();
192
+ if (!stats) {
193
+ throw new Error("Should generate stats during build");
194
+ }
195
+ const jsonStats = stats.toJson({
196
+ // errorDetails: true
197
+ });
198
+ const compilerOptions = compiler.getOptions();
114
199
  const updateIndex = updatePlugin.getUpdateIndex();
115
- const totalUpdates = updatePlugin.getTotalUpdates();
116
- if (updateIndex + 1 !== totalUpdates) {
117
- throw new Error(`Should run all hot steps (${updateIndex + 1} / ${totalUpdates}): ${this._options.name}`);
200
+ await (0, checkArrayExpectation_1.default)(source, jsonStats, "error", `errors${updateIndex}`, "Error", compilerOptions);
201
+ await (0, checkArrayExpectation_1.default)(source, jsonStats, "warning", `warnings${updateIndex}`, "Warning", compilerOptions);
202
+ const updatedModules = await m.hot.check(options || true);
203
+ if (!updatedModules) {
204
+ throw new Error("No update available");
118
205
  }
206
+ return jsonStats;
119
207
  };
120
- return processor;
121
- }
122
- function getCreator(target) {
123
- if (!creators.has(target)) {
124
- creators.set(target, new creator_1.BasicCaseCreator({
125
- clean: true,
126
- describe: true,
127
- target,
128
- steps: ({ name, src, target, temp }) => [
129
- createCacheProcessor(name, src, temp, target)
130
- ],
131
- runner: runner_1.CacheRunnerFactory,
132
- concurrent: true
133
- }));
134
- }
135
- return creators.get(target);
136
- }
137
- function createCacheCase(name, src, dist, target, temp) {
138
- const creator = getCreator(target);
139
- creator.create(name, src, dist, temp);
208
+ const nextStart = async () => {
209
+ await compiler.close();
210
+ compiler.createCompiler();
211
+ await updatePlugin.goNext();
212
+ const stats = await compiler.build();
213
+ if (!stats) {
214
+ throw new Error("Should generate stats during build");
215
+ }
216
+ const jsonStats = stats.toJson({
217
+ // errorDetails: true
218
+ });
219
+ const compilerOptions = compiler.getOptions();
220
+ const updateIndex = updatePlugin.getUpdateIndex();
221
+ await (0, checkArrayExpectation_1.default)(source, jsonStats, "error", `errors${updateIndex}`, "Error", compilerOptions);
222
+ await (0, checkArrayExpectation_1.default)(source, jsonStats, "warning", `warnings${updateIndex}`, "Warning", compilerOptions);
223
+ env.it(`NEXT_START run with compilerIndex==${compilerIndex + 1}`, async () => {
224
+ if (compilerIndex > MAX_COMPILER_INDEX) {
225
+ throw new Error("NEXT_START has been called more than the maximum times");
226
+ }
227
+ compilerIndex++;
228
+ return getWebRunner().run(file);
229
+ });
230
+ return jsonStats;
231
+ };
232
+ return getWebRunner();
140
233
  }
@@ -0,0 +1,10 @@
1
+ import { ECompilerType, type ITestCompilerManager, type ITestContext, type ITestEnv, type TCompiler, type TCompilerOptions } from "../type";
2
+ export declare function getCompiler<T extends ECompilerType = ECompilerType.Rspack>(context: ITestContext, name: string): ITestCompilerManager<T>;
3
+ export declare function config<T extends ECompilerType = ECompilerType.Rspack>(context: ITestContext, name: string, configFiles: string[], defaultOptions?: TCompilerOptions<T>): Promise<TCompilerOptions<T>>;
4
+ export declare function compiler<T extends ECompilerType = ECompilerType.Rspack>(context: ITestContext, name: string): Promise<TCompiler<T>>;
5
+ export declare function build<T extends ECompilerType = ECompilerType.Rspack>(context: ITestContext, name: string): Promise<TCompiler<T>>;
6
+ export declare function run<T extends ECompilerType = ECompilerType.Rspack>(env: ITestEnv, context: ITestContext, name: string, findBundle: (context: ITestContext, options: TCompilerOptions<T>) => string[] | string | void): Promise<void>;
7
+ export declare function check<T extends ECompilerType = ECompilerType.Rspack>(env: ITestEnv, context: ITestContext, name: string): Promise<void>;
8
+ export declare function checkSnapshot<T extends ECompilerType = ECompilerType.Rspack>(env: ITestEnv, context: ITestContext, name: string, snapshot: string, filter?: (file: string) => boolean): Promise<void>;
9
+ export declare function findMultiCompilerBundle<T extends ECompilerType = ECompilerType.Rspack>(context: ITestContext, name: string, multiFindBundle: (index: number, context: ITestContext, options: TCompilerOptions<T>) => string[] | string | void): string[];
10
+ export declare function configMultiCompiler<T extends ECompilerType = ECompilerType.Rspack>(context: ITestContext, name: string, configFiles: string[], defaultOptions: (index: number, context: ITestContext) => TCompilerOptions<T>, overrideOptions: (index: number, context: ITestContext, options: TCompilerOptions<T>) => void): void;
@@ -0,0 +1,237 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.getCompiler = getCompiler;
7
+ exports.config = config;
8
+ exports.compiler = compiler;
9
+ exports.build = build;
10
+ exports.run = run;
11
+ exports.check = check;
12
+ exports.checkSnapshot = checkSnapshot;
13
+ exports.findMultiCompilerBundle = findMultiCompilerBundle;
14
+ exports.configMultiCompiler = configMultiCompiler;
15
+ const fs_extra_1 = __importDefault(require("fs-extra"));
16
+ const path_1 = __importDefault(require("path"));
17
+ const webpack_merge_1 = __importDefault(require("webpack-merge"));
18
+ const helper_1 = require("../helper");
19
+ const placeholder_1 = require("../helper/expect/placeholder");
20
+ const checkArrayExpectation_1 = __importDefault(require("../helper/legacy/checkArrayExpectation"));
21
+ const type_1 = require("../type");
22
+ function getCompiler(context, name) {
23
+ return context.getCompiler(name, type_1.ECompilerType.Rspack);
24
+ }
25
+ async function config(context, name, configFiles, defaultOptions = {}) {
26
+ const compiler = getCompiler(context, name);
27
+ compiler.setOptions(defaultOptions);
28
+ if (Array.isArray(configFiles)) {
29
+ const fileOptions = (0, helper_1.readConfigFile)(configFiles.map(i => context.getSource(i)))[0];
30
+ compiler.mergeOptions(fileOptions);
31
+ }
32
+ return compiler.getOptions();
33
+ }
34
+ async function compiler(context, name) {
35
+ const compiler = getCompiler(context, name);
36
+ compiler.createCompiler();
37
+ return compiler.getCompiler();
38
+ }
39
+ async function build(context, name) {
40
+ const compiler = getCompiler(context, name);
41
+ await compiler.build();
42
+ return compiler.getCompiler();
43
+ }
44
+ async function run(env, context, name, findBundle) {
45
+ const testConfig = context.getTestConfig();
46
+ if (testConfig.noTests)
47
+ return;
48
+ if (testConfig.documentType) {
49
+ context.setValue(name, "documentType", testConfig.documentType);
50
+ }
51
+ const compiler = getCompiler(context, name);
52
+ if (typeof testConfig.beforeExecute === "function") {
53
+ testConfig.beforeExecute(compiler.getOptions());
54
+ }
55
+ let bundles;
56
+ if (testConfig.bundlePath) {
57
+ bundles = testConfig.bundlePath;
58
+ }
59
+ else if (typeof findBundle === "function") {
60
+ bundles = findBundle(context, compiler.getOptions());
61
+ }
62
+ else {
63
+ bundles = [];
64
+ }
65
+ if (typeof bundles === "string") {
66
+ bundles = [bundles];
67
+ }
68
+ if (!bundles || !bundles.length) {
69
+ return;
70
+ }
71
+ for (const bundle of bundles) {
72
+ if (!bundle) {
73
+ continue;
74
+ }
75
+ const runner = context.getRunner(name, bundle, env);
76
+ const mod = runner.run(bundle);
77
+ const result = context.getValue(name, "modules") || [];
78
+ result.push(mod);
79
+ context.setValue(name, "modules", result);
80
+ }
81
+ const results = context.getValue(name, "modules") || [];
82
+ await Promise.all(results);
83
+ if (typeof testConfig.afterExecute === "function") {
84
+ testConfig.afterExecute(compiler.getOptions());
85
+ }
86
+ }
87
+ async function check(env, context, name) {
88
+ const testConfig = context.getTestConfig();
89
+ if (testConfig.noTests)
90
+ return;
91
+ const compiler = getCompiler(context, name);
92
+ const errors = (context.getError(name) || []).map(e => ({
93
+ message: e.message,
94
+ stack: e.stack
95
+ }));
96
+ const warnings = [];
97
+ const stats = compiler.getStats();
98
+ const options = compiler.getOptions();
99
+ if (stats) {
100
+ if (testConfig.writeStatsOuptut) {
101
+ fs_extra_1.default.writeFileSync(path_1.default.join(context.getDist(), "stats.txt"), stats.toString({
102
+ preset: "verbose",
103
+ colors: false
104
+ }), "utf-8");
105
+ }
106
+ if (testConfig.writeStatsJson) {
107
+ const jsonStats = stats.toJson({
108
+ errorDetails: true
109
+ });
110
+ fs_extra_1.default.writeFileSync(path_1.default.join(context.getDist(), "stats.json"), JSON.stringify(jsonStats, null, 2), "utf-8");
111
+ }
112
+ if (fs_extra_1.default.existsSync(context.getSource("errors.js")) ||
113
+ fs_extra_1.default.existsSync(context.getSource("warnings.js")) ||
114
+ stats.hasErrors() ||
115
+ stats.hasWarnings()) {
116
+ const statsJson = stats.toJson({
117
+ errorDetails: true
118
+ });
119
+ if (statsJson.errors) {
120
+ errors.push(...statsJson.errors);
121
+ }
122
+ if (statsJson.warnings) {
123
+ warnings.push(...statsJson.warnings);
124
+ }
125
+ }
126
+ }
127
+ await (0, checkArrayExpectation_1.default)(context.getSource(), { errors }, "error", "errors", "Error", options);
128
+ await (0, checkArrayExpectation_1.default)(context.getSource(), { warnings }, "warning", "warnings", "Warning", options);
129
+ // clear error if checked
130
+ if (fs_extra_1.default.existsSync(context.getSource("errors.js"))) {
131
+ context.clearError(name);
132
+ }
133
+ }
134
+ async function checkSnapshot(env, context, name, snapshot, filter) {
135
+ if (path_1.default.extname(snapshot) === ".snap") {
136
+ throw new Error("Snapshot with `.snap` will be managed by jest, please use `.snap.txt` instead");
137
+ }
138
+ const compiler = getCompiler(context, name);
139
+ const stats = compiler.getStats();
140
+ const c = compiler.getCompiler();
141
+ if (!stats || !c)
142
+ return;
143
+ if (stats.hasErrors()) {
144
+ const errors = [];
145
+ if (stats.stats) {
146
+ for (const s of stats.stats) {
147
+ if (s.hasErrors()) {
148
+ errors.push(...s.compilation.errors);
149
+ }
150
+ }
151
+ }
152
+ else {
153
+ const s = stats;
154
+ errors.push(...s.compilation.errors);
155
+ }
156
+ throw new Error(`Failed to compile in fixture ${name}, Errors: ${errors
157
+ ?.map(i => `${i.message}\n${i.stack}`)
158
+ .join("\n\n")}`);
159
+ }
160
+ const compilation = c._lastCompilation ||
161
+ c._lastCompilation;
162
+ const snapshotFileFilter = filter ||
163
+ ((file) => file.endsWith(".js") && !file.includes("runtime.js"));
164
+ const fileContents = Object.entries(compilation.assets)
165
+ .filter(([file]) => snapshotFileFilter(file))
166
+ .map(([file, source]) => {
167
+ const tag = path_1.default.extname(file).slice(1) || "txt";
168
+ let content = (0, placeholder_1.normalizePlaceholder)(source.source().toString());
169
+ const testConfig = context.getTestConfig();
170
+ if (testConfig.snapshotContent) {
171
+ content = testConfig.snapshotContent(content);
172
+ }
173
+ return `\`\`\`${tag} title=${file}\n${content}\n\`\`\``;
174
+ });
175
+ fileContents.sort();
176
+ const content = fileContents.join("\n\n");
177
+ const snapshotPath = path_1.default.isAbsolute(snapshot)
178
+ ? snapshot
179
+ : path_1.default.resolve(context.getSource(), `./__snapshots__/${snapshot}`);
180
+ env.expect(content).toMatchFileSnapshot(snapshotPath);
181
+ }
182
+ function findMultiCompilerBundle(context, name, multiFindBundle) {
183
+ if (typeof multiFindBundle !== "function") {
184
+ return [];
185
+ }
186
+ const multiCompilerOptions = (context.getValue(name, "multiCompilerOptions") || []);
187
+ const result = [];
188
+ const multiFileIndexMap = context.getValue(name, "multiFileIndexMap") || {};
189
+ for (const [index, compilerOptions] of multiCompilerOptions.entries()) {
190
+ const curBundles = multiFindBundle(index, context, compilerOptions);
191
+ const bundles = Array.isArray(curBundles)
192
+ ? curBundles
193
+ : curBundles
194
+ ? [curBundles]
195
+ : [];
196
+ for (const bundle of bundles) {
197
+ if (multiFileIndexMap[bundle]) {
198
+ multiFileIndexMap[bundle].push(index);
199
+ }
200
+ else {
201
+ multiFileIndexMap[bundle] = [index];
202
+ }
203
+ }
204
+ result.push(...bundles);
205
+ }
206
+ context.setValue(name, "multiFileIndexMap", multiFileIndexMap);
207
+ return result;
208
+ }
209
+ function configMultiCompiler(context, name, configFiles, defaultOptions, overrideOptions) {
210
+ const multiCompilerOptions = [];
211
+ const caseOptions = Array.isArray(configFiles)
212
+ ? (0, helper_1.readConfigFile)(configFiles.map(i => context.getSource(i)), configs => {
213
+ return configs.flatMap(c => {
214
+ if (typeof c === "function") {
215
+ const options = {
216
+ testPath: context.getDist(),
217
+ env: undefined
218
+ };
219
+ return c(options.env, options);
220
+ }
221
+ return c;
222
+ });
223
+ })
224
+ : [{}];
225
+ for (const [index, options] of caseOptions.entries()) {
226
+ const compilerOptions = (0, webpack_merge_1.default)(typeof defaultOptions === "function"
227
+ ? defaultOptions(index, context)
228
+ : {}, options);
229
+ if (typeof overrideOptions === "function") {
230
+ overrideOptions(index, context, compilerOptions);
231
+ }
232
+ multiCompilerOptions.push(compilerOptions);
233
+ }
234
+ const compiler = getCompiler(context, name);
235
+ compiler.setOptions(multiCompilerOptions);
236
+ context.setValue(name, "multiCompilerOptions", multiCompilerOptions);
237
+ }
@@ -1,9 +1,12 @@
1
- import { type ISimpleProcessorOptions } from "../processor";
2
- import { ECompilerType, type ITestContext, type TCompilation, type TCompiler, type TCompilerStatsCompilation } from "../type";
3
- export type TCompilerCaseConfig = Omit<ISimpleProcessorOptions<ECompilerType.Rspack>, "name" | "compilerType" | "check"> & {
1
+ import type { ECompilerType, ITestContext, TCompilation, TCompiler, TCompilerOptions, TCompilerStats, TCompilerStatsCompilation } from "../type";
2
+ export declare function createCompilerCase(name: string, src: string, dist: string, testConfig: string): void;
3
+ export type TCompilerCaseConfig = {
4
4
  description: string;
5
5
  error?: boolean;
6
6
  skip?: boolean;
7
+ options?: (context: ITestContext) => TCompilerOptions<ECompilerType.Rspack>;
8
+ compiler?: (context: ITestContext, compiler: TCompiler<ECompilerType.Rspack>) => Promise<void>;
9
+ build?: (context: ITestContext, compiler: TCompiler<ECompilerType.Rspack>) => Promise<void>;
7
10
  check?: ({ context, stats, files, compiler, compilation }: {
8
11
  context: ITestContext;
9
12
  stats?: TCompilerStatsCompilation<ECompilerType.Rspack>;
@@ -11,5 +14,5 @@ export type TCompilerCaseConfig = Omit<ISimpleProcessorOptions<ECompilerType.Rsp
11
14
  compiler: TCompiler<ECompilerType.Rspack>;
12
15
  compilation?: TCompilation<ECompilerType.Rspack>;
13
16
  }) => Promise<void>;
17
+ compilerCallback?: (error: Error | null, stats: TCompilerStats<ECompilerType.Rspack> | null) => void;
14
18
  };
15
- export declare function createCompilerCase(name: string, src: string, dist: string, testConfig: string): void;