@rspack-debug/test-tools 1.3.14

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 (262) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +17 -0
  3. package/dist/case/builtin.d.ts +1 -0
  4. package/dist/case/builtin.js +39 -0
  5. package/dist/case/cache.d.ts +2 -0
  6. package/dist/case/cache.js +34 -0
  7. package/dist/case/compiler.d.ts +6 -0
  8. package/dist/case/compiler.js +17 -0
  9. package/dist/case/config.d.ts +3 -0
  10. package/dist/case/config.js +39 -0
  11. package/dist/case/defaults.d.ts +6 -0
  12. package/dist/case/defaults.js +39 -0
  13. package/dist/case/diagnostic.d.ts +1 -0
  14. package/dist/case/diagnostic.js +29 -0
  15. package/dist/case/diff.d.ts +3 -0
  16. package/dist/case/diff.js +126 -0
  17. package/dist/case/error.d.ts +6 -0
  18. package/dist/case/error.js +21 -0
  19. package/dist/case/hash.d.ts +3 -0
  20. package/dist/case/hash.js +30 -0
  21. package/dist/case/hook.d.ts +6 -0
  22. package/dist/case/hook.js +35 -0
  23. package/dist/case/hot-step.d.ts +2 -0
  24. package/dist/case/hot-step.js +32 -0
  25. package/dist/case/hot.d.ts +2 -0
  26. package/dist/case/hot.js +32 -0
  27. package/dist/case/index.d.ts +19 -0
  28. package/dist/case/index.js +35 -0
  29. package/dist/case/new-incremental.d.ts +6 -0
  30. package/dist/case/new-incremental.js +100 -0
  31. package/dist/case/normal.d.ts +1 -0
  32. package/dist/case/normal.js +29 -0
  33. package/dist/case/serial.d.ts +3 -0
  34. package/dist/case/serial.js +34 -0
  35. package/dist/case/stats-api.d.ts +6 -0
  36. package/dist/case/stats-api.js +21 -0
  37. package/dist/case/stats-output.d.ts +1 -0
  38. package/dist/case/stats-output.js +22 -0
  39. package/dist/case/treeshaking.d.ts +1 -0
  40. package/dist/case/treeshaking.js +23 -0
  41. package/dist/case/watch.d.ts +1 -0
  42. package/dist/case/watch.js +53 -0
  43. package/dist/compare/comparator.d.ts +17 -0
  44. package/dist/compare/comparator.js +52 -0
  45. package/dist/compare/compare.d.ts +17 -0
  46. package/dist/compare/compare.js +175 -0
  47. package/dist/compare/format-code.d.ts +16 -0
  48. package/dist/compare/format-code.js +239 -0
  49. package/dist/compare/index.d.ts +5 -0
  50. package/dist/compare/index.js +21 -0
  51. package/dist/compare/replace-module-argument.d.ts +1 -0
  52. package/dist/compare/replace-module-argument.js +8 -0
  53. package/dist/compare/replace-runtime-module-name.d.ts +1 -0
  54. package/dist/compare/replace-runtime-module-name.js +71 -0
  55. package/dist/compiler.d.ts +28 -0
  56. package/dist/compiler.js +111 -0
  57. package/dist/helper/directory.d.ts +12 -0
  58. package/dist/helper/directory.js +81 -0
  59. package/dist/helper/expect/diff.d.ts +3 -0
  60. package/dist/helper/expect/diff.js +21 -0
  61. package/dist/helper/expect/error.d.ts +5 -0
  62. package/dist/helper/expect/error.js +51 -0
  63. package/dist/helper/expect/placeholder.d.ts +1 -0
  64. package/dist/helper/expect/placeholder.js +41 -0
  65. package/dist/helper/expect/rspack.d.ts +3 -0
  66. package/dist/helper/expect/rspack.js +14 -0
  67. package/dist/helper/expect/to-be-typeof.d.ts +4 -0
  68. package/dist/helper/expect/to-be-typeof.js +12 -0
  69. package/dist/helper/expect/to-end-with.d.ts +4 -0
  70. package/dist/helper/expect/to-end-with.js +11 -0
  71. package/dist/helper/expect/to-match-file-snapshot.d.ts +23 -0
  72. package/dist/helper/expect/to-match-file-snapshot.js +108 -0
  73. package/dist/helper/hot-update/index.d.ts +1 -0
  74. package/dist/helper/hot-update/index.js +5 -0
  75. package/dist/helper/hot-update/loader.d.ts +1 -0
  76. package/dist/helper/hot-update/loader.js +32 -0
  77. package/dist/helper/hot-update/plugin.d.ts +17 -0
  78. package/dist/helper/hot-update/plugin.js +133 -0
  79. package/dist/helper/index.d.ts +7 -0
  80. package/dist/helper/index.js +23 -0
  81. package/dist/helper/legacy/EventSourceForNode.d.ts +8 -0
  82. package/dist/helper/legacy/EventSourceForNode.js +40 -0
  83. package/dist/helper/legacy/FakeDocument.d.ts +54 -0
  84. package/dist/helper/legacy/FakeDocument.js +278 -0
  85. package/dist/helper/legacy/asModule.d.ts +3 -0
  86. package/dist/helper/legacy/asModule.js +25 -0
  87. package/dist/helper/legacy/captureStdio.d.ts +8 -0
  88. package/dist/helper/legacy/captureStdio.js +32 -0
  89. package/dist/helper/legacy/checkArrayExpectation.d.ts +2 -0
  90. package/dist/helper/legacy/checkArrayExpectation.js +111 -0
  91. package/dist/helper/legacy/copyDiff.d.ts +2 -0
  92. package/dist/helper/legacy/copyDiff.js +33 -0
  93. package/dist/helper/legacy/createFakeWorker.d.ts +13 -0
  94. package/dist/helper/legacy/createFakeWorker.js +80 -0
  95. package/dist/helper/legacy/createLazyTestEnv.d.ts +10 -0
  96. package/dist/helper/legacy/createLazyTestEnv.js +116 -0
  97. package/dist/helper/legacy/createLogger.d.ts +23 -0
  98. package/dist/helper/legacy/createLogger.js +20 -0
  99. package/dist/helper/legacy/currentScript.d.ts +6 -0
  100. package/dist/helper/legacy/currentScript.js +8 -0
  101. package/dist/helper/legacy/fakeSystem.d.ts +9 -0
  102. package/dist/helper/legacy/fakeSystem.js +124 -0
  103. package/dist/helper/legacy/parseResource.d.ts +6 -0
  104. package/dist/helper/legacy/parseResource.js +15 -0
  105. package/dist/helper/legacy/supportsImportFn.d.ts +1 -0
  106. package/dist/helper/legacy/supportsImportFn.js +15 -0
  107. package/dist/helper/legacy/supportsWorker.d.ts +2 -0
  108. package/dist/helper/legacy/supportsWorker.js +17 -0
  109. package/dist/helper/legacy/urlToRelativePath.d.ts +2 -0
  110. package/dist/helper/legacy/urlToRelativePath.js +7 -0
  111. package/dist/helper/legacy/walkCssTokens.d.ts +40 -0
  112. package/dist/helper/legacy/walkCssTokens.js +761 -0
  113. package/dist/helper/legacy/warmup-webpack.d.ts +1 -0
  114. package/dist/helper/legacy/warmup-webpack.js +26 -0
  115. package/dist/helper/loaders/hot-update.d.ts +1 -0
  116. package/dist/helper/loaders/hot-update.js +40 -0
  117. package/dist/helper/parse-modules.d.ts +7 -0
  118. package/dist/helper/parse-modules.js +73 -0
  119. package/dist/helper/plugins/hot-update.d.ts +7 -0
  120. package/dist/helper/plugins/hot-update.js +40 -0
  121. package/dist/helper/plugins/index.d.ts +1 -0
  122. package/dist/helper/plugins/index.js +17 -0
  123. package/dist/helper/read-config-file.d.ts +2 -0
  124. package/dist/helper/read-config-file.js +13 -0
  125. package/dist/helper/serializers.d.ts +2 -0
  126. package/dist/helper/serializers.js +52 -0
  127. package/dist/helper/setup-env.d.ts +1 -0
  128. package/dist/helper/setup-env.js +80 -0
  129. package/dist/helper/setup-expect.d.ts +1 -0
  130. package/dist/helper/setup-expect.js +16 -0
  131. package/dist/helper/update-snapshot.d.ts +1 -0
  132. package/dist/helper/update-snapshot.js +6 -0
  133. package/dist/helper/util/checkSourceMap.d.ts +1 -0
  134. package/dist/helper/util/checkSourceMap.js +96 -0
  135. package/dist/helper/util/checkStats.d.ts +2 -0
  136. package/dist/helper/util/checkStats.js +43 -0
  137. package/dist/helper/util/currentWatchStep.d.ts +1 -0
  138. package/dist/helper/util/currentWatchStep.js +2 -0
  139. package/dist/helper/util/expectWarningFactory.d.ts +2 -0
  140. package/dist/helper/util/expectWarningFactory.js +21 -0
  141. package/dist/helper/util/filterUtil.d.ts +8 -0
  142. package/dist/helper/util/filterUtil.js +50 -0
  143. package/dist/helper/util/identifier.d.ts +76 -0
  144. package/dist/helper/util/identifier.js +339 -0
  145. package/dist/helper/util/replaceMitteDiagnostic.d.ts +2 -0
  146. package/dist/helper/util/replaceMitteDiagnostic.js +17 -0
  147. package/dist/helper/win.d.ts +1 -0
  148. package/dist/helper/win.js +10 -0
  149. package/dist/index.d.ts +12 -0
  150. package/dist/index.js +28 -0
  151. package/dist/plugin/index.d.ts +4 -0
  152. package/dist/plugin/index.js +20 -0
  153. package/dist/plugin/lazy-compilation-test-plugin.d.ts +4 -0
  154. package/dist/plugin/lazy-compilation-test-plugin.js +67 -0
  155. package/dist/plugin/rspack-diff-config-plugin.d.ts +7 -0
  156. package/dist/plugin/rspack-diff-config-plugin.js +42 -0
  157. package/dist/plugin/webpack-diff-config-plugin.d.ts +7 -0
  158. package/dist/plugin/webpack-diff-config-plugin.js +41 -0
  159. package/dist/plugin/webpack-module-placeholder-plugin.d.ts +3 -0
  160. package/dist/plugin/webpack-module-placeholder-plugin.js +107 -0
  161. package/dist/processor/basic.d.ts +24 -0
  162. package/dist/processor/basic.js +146 -0
  163. package/dist/processor/builtin.d.ts +9 -0
  164. package/dist/processor/builtin.js +171 -0
  165. package/dist/processor/cache.d.ts +20 -0
  166. package/dist/processor/cache.js +127 -0
  167. package/dist/processor/config.d.ts +11 -0
  168. package/dist/processor/config.js +81 -0
  169. package/dist/processor/defaults.d.ts +30 -0
  170. package/dist/processor/defaults.js +72 -0
  171. package/dist/processor/diagnostic.d.ts +15 -0
  172. package/dist/processor/diagnostic.js +102 -0
  173. package/dist/processor/diff.d.ts +30 -0
  174. package/dist/processor/diff.js +140 -0
  175. package/dist/processor/error.d.ts +23 -0
  176. package/dist/processor/error.js +95 -0
  177. package/dist/processor/hash.d.ts +10 -0
  178. package/dist/processor/hash.js +63 -0
  179. package/dist/processor/hook.d.ts +44 -0
  180. package/dist/processor/hook.js +204 -0
  181. package/dist/processor/hot-new-incremental.d.ts +14 -0
  182. package/dist/processor/hot-new-incremental.js +43 -0
  183. package/dist/processor/hot-step.d.ts +18 -0
  184. package/dist/processor/hot-step.js +299 -0
  185. package/dist/processor/hot.d.ts +17 -0
  186. package/dist/processor/hot.js +138 -0
  187. package/dist/processor/index.d.ts +20 -0
  188. package/dist/processor/index.js +36 -0
  189. package/dist/processor/multi.d.ts +17 -0
  190. package/dist/processor/multi.js +73 -0
  191. package/dist/processor/normal.d.ts +12 -0
  192. package/dist/processor/normal.js +150 -0
  193. package/dist/processor/simple.d.ts +23 -0
  194. package/dist/processor/simple.js +49 -0
  195. package/dist/processor/snapshot.d.ts +12 -0
  196. package/dist/processor/snapshot.js +62 -0
  197. package/dist/processor/stats-api.d.ts +18 -0
  198. package/dist/processor/stats-api.js +48 -0
  199. package/dist/processor/stats.d.ts +18 -0
  200. package/dist/processor/stats.js +206 -0
  201. package/dist/processor/treeshaking.d.ts +10 -0
  202. package/dist/processor/treeshaking.js +33 -0
  203. package/dist/processor/watch.d.ts +29 -0
  204. package/dist/processor/watch.js +234 -0
  205. package/dist/reporter/diff-html.d.ts +15 -0
  206. package/dist/reporter/diff-html.js +69 -0
  207. package/dist/reporter/diff-stats.d.ts +24 -0
  208. package/dist/reporter/diff-stats.js +131 -0
  209. package/dist/reporter/index.d.ts +2 -0
  210. package/dist/reporter/index.js +18 -0
  211. package/dist/runner/basic.d.ts +10 -0
  212. package/dist/runner/basic.js +63 -0
  213. package/dist/runner/cache.d.ts +5 -0
  214. package/dist/runner/cache.js +90 -0
  215. package/dist/runner/hot-step.d.ts +5 -0
  216. package/dist/runner/hot-step.js +87 -0
  217. package/dist/runner/hot.d.ts +5 -0
  218. package/dist/runner/hot.js +83 -0
  219. package/dist/runner/index.d.ts +9 -0
  220. package/dist/runner/index.js +25 -0
  221. package/dist/runner/multiple.d.ts +11 -0
  222. package/dist/runner/multiple.js +38 -0
  223. package/dist/runner/normal.d.ts +5 -0
  224. package/dist/runner/normal.js +20 -0
  225. package/dist/runner/runner/basic.d.ts +30 -0
  226. package/dist/runner/runner/basic.js +107 -0
  227. package/dist/runner/runner/cjs.d.ts +14 -0
  228. package/dist/runner/runner/cjs.js +151 -0
  229. package/dist/runner/runner/esm.d.ts +7 -0
  230. package/dist/runner/runner/esm.js +125 -0
  231. package/dist/runner/runner/index.d.ts +8 -0
  232. package/dist/runner/runner/index.js +24 -0
  233. package/dist/runner/runner/normal.d.ts +9 -0
  234. package/dist/runner/runner/normal.js +23 -0
  235. package/dist/runner/runner/watch.d.ts +16 -0
  236. package/dist/runner/runner/watch.js +27 -0
  237. package/dist/runner/runner/web/fake.d.ts +18 -0
  238. package/dist/runner/runner/web/fake.js +143 -0
  239. package/dist/runner/runner/web/jsdom.d.ts +26 -0
  240. package/dist/runner/runner/web/jsdom.js +219 -0
  241. package/dist/runner/runner/web.d.ts +15 -0
  242. package/dist/runner/runner/web.js +32 -0
  243. package/dist/runner/type.d.ts +42 -0
  244. package/dist/runner/type.js +9 -0
  245. package/dist/runner/watch.d.ts +7 -0
  246. package/dist/runner/watch.js +60 -0
  247. package/dist/test/context.d.ts +26 -0
  248. package/dist/test/context.js +108 -0
  249. package/dist/test/creator.d.ts +46 -0
  250. package/dist/test/creator.js +310 -0
  251. package/dist/test/simple.d.ts +5 -0
  252. package/dist/test/simple.js +43 -0
  253. package/dist/test/tester.d.ts +17 -0
  254. package/dist/test/tester.js +88 -0
  255. package/dist/type.d.ts +168 -0
  256. package/dist/type.js +22 -0
  257. package/jest.d.ts +25 -0
  258. package/package.json +116 -0
  259. package/template/diff.bundle.css +1 -0
  260. package/template/diff.bundle.js +144 -0
  261. package/template/diff.html +14 -0
  262. package/template/editor.worker.js +1 -0
@@ -0,0 +1,44 @@
1
+ import { type TTestContextOptions, TestContext } from "../test/context";
2
+ import type { ECompilerType, ITestContext, ITestEnv, TCompiler, TCompilerOptions } from "../type";
3
+ import { type ISnapshotProcessorOptions, SnapshotProcessor } from "./snapshot";
4
+ export declare class HookCasesContext extends TestContext {
5
+ protected src: string;
6
+ protected testName: string;
7
+ protected options: TTestContextOptions;
8
+ protected promises: Promise<void>[];
9
+ protected count: number;
10
+ protected snapshots: Record<string | number, Array<[string | Buffer, string]>>;
11
+ protected snapshotsList: Array<string | number>;
12
+ constructor(src: string, testName: string, options: TTestContextOptions);
13
+ /**
14
+ * Snapshot function arguments and return value.
15
+ * Generated snapshot is located in the same directory with the test source.
16
+ * @example
17
+ * compiler.hooks.compilation("name", context.snapped((...args) => { ... }))
18
+ */
19
+ snapped(cb: (...args: unknown[]) => Promise<unknown>, prefix?: string): (this: any, ...args: unknown[]) => Promise<unknown>;
20
+ /**
21
+ * @internal
22
+ */
23
+ _addSnapshot(content: unknown, name: string, group: string | number): void;
24
+ /**
25
+ * @internal
26
+ */
27
+ collectSnapshots(env: ITestEnv, options?: {
28
+ diff: {};
29
+ }): Promise<void>;
30
+ }
31
+ export interface IHookProcessorOptions<T extends ECompilerType> extends ISnapshotProcessorOptions<T> {
32
+ options?: (context: ITestContext) => TCompilerOptions<T>;
33
+ compiler?: (context: ITestContext, compiler: TCompiler<T>) => Promise<void>;
34
+ check?: (context: ITestContext) => Promise<void>;
35
+ }
36
+ export declare class HookTaskProcessor<T extends ECompilerType> extends SnapshotProcessor<T> {
37
+ protected _hookOptions: IHookProcessorOptions<T>;
38
+ constructor(_hookOptions: IHookProcessorOptions<T>);
39
+ config(context: ITestContext): Promise<void>;
40
+ compiler(context: ITestContext): Promise<void>;
41
+ check(env: ITestEnv, context: HookCasesContext): Promise<void>;
42
+ static defaultOptions<T extends ECompilerType>(context: ITestContext): TCompilerOptions<T>;
43
+ static overrideOptions<T extends ECompilerType>(options: TCompilerOptions<T>): void;
44
+ }
@@ -0,0 +1,204 @@
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.HookTaskProcessor = exports.HookCasesContext = void 0;
7
+ const node_path_1 = __importDefault(require("node:path"));
8
+ const core_1 = require("@rspack/core");
9
+ const jest_snapshot_1 = require("jest-snapshot");
10
+ const pretty_format_1 = require("pretty-format");
11
+ const path_serializer_1 = require("path-serializer");
12
+ const context_1 = require("../test/context");
13
+ const snapshot_1 = require("./snapshot");
14
+ const srcDir = node_path_1.default.resolve(__dirname, "../../tests/fixtures");
15
+ const distDir = node_path_1.default.resolve(__dirname, "../../tests/js/hook");
16
+ const sourceSerializer = {
17
+ test(val) {
18
+ return val instanceof core_1.sources.Source;
19
+ },
20
+ print(val) {
21
+ return val.source();
22
+ }
23
+ };
24
+ const internalSerializer = {
25
+ test(val) {
26
+ return val instanceof core_1.Compiler || val instanceof core_1.Compilation;
27
+ },
28
+ print(val) {
29
+ return JSON.stringify(`${val.constructor.name}(internal ignored)`);
30
+ }
31
+ };
32
+ const testPathSerializer = (0, path_serializer_1.createSnapshotSerializer)({
33
+ replace: [
34
+ {
35
+ match: srcDir,
36
+ mark: "<HOOK_SRC_DIR>"
37
+ },
38
+ {
39
+ match: distDir,
40
+ mark: "<HOOK_DIST_DIR>"
41
+ }
42
+ ]
43
+ });
44
+ const escapeRegex = true;
45
+ const printFunctionName = false;
46
+ const normalizeNewlines = (str) => str.replace(/\r\n|\r/g, "\n");
47
+ const serialize = (val, indent = 2, formatOverrides = {}) => normalizeNewlines((0, pretty_format_1.format)(val, {
48
+ escapeRegex,
49
+ indent,
50
+ plugins: [
51
+ ...(0, jest_snapshot_1.getSerializers)(),
52
+ sourceSerializer,
53
+ internalSerializer,
54
+ testPathSerializer
55
+ ],
56
+ printFunctionName,
57
+ ...formatOverrides
58
+ }));
59
+ class HookCasesContext extends context_1.TestContext {
60
+ constructor(src, testName, options) {
61
+ super(options);
62
+ this.src = src;
63
+ this.testName = testName;
64
+ this.options = options;
65
+ this.promises = [];
66
+ this.count = 0;
67
+ this.snapshots = {};
68
+ this.snapshotsList = [];
69
+ this.snapped = this.snapped.bind(this);
70
+ }
71
+ /**
72
+ * Snapshot function arguments and return value.
73
+ * Generated snapshot is located in the same directory with the test source.
74
+ * @example
75
+ * compiler.hooks.compilation("name", context.snapped((...args) => { ... }))
76
+ */
77
+ snapped(cb, prefix = "") {
78
+ // eslint-disable-next-line
79
+ const context = this;
80
+ return function SNAPPED_HOOK(...args) {
81
+ const group = prefix ? prefix : context.count++;
82
+ context._addSnapshot(args, "input", group);
83
+ const output = cb.apply(this, args);
84
+ if (output && typeof output.then === "function") {
85
+ let resolve;
86
+ context.promises.push(new Promise(r => (resolve = r)));
87
+ return output
88
+ .then((o) => {
89
+ context._addSnapshot(o, "output (Promise resolved)", group);
90
+ return o;
91
+ })
92
+ .catch((o) => {
93
+ context._addSnapshot(o, "output (Promise rejected)", group);
94
+ return o;
95
+ })
96
+ .finally(resolve);
97
+ }
98
+ context._addSnapshot(output, "output", group);
99
+ return output;
100
+ };
101
+ }
102
+ /**
103
+ * @internal
104
+ */
105
+ _addSnapshot(content, name, group) {
106
+ const normalizedContent = Buffer.isBuffer(content)
107
+ ? content
108
+ : serialize(content, undefined, {
109
+ escapeString: true,
110
+ printBasicPrototype: true
111
+ }).replace(/\r\n/g, "\n");
112
+ (this.snapshots[group] = this.snapshots[group] || []).push([
113
+ normalizedContent,
114
+ name
115
+ ]);
116
+ if (!this.snapshotsList.includes(group)) {
117
+ this.snapshotsList.push(group);
118
+ }
119
+ }
120
+ /**
121
+ * @internal
122
+ */
123
+ async collectSnapshots(env, options = {
124
+ diff: {}
125
+ }) {
126
+ await Promise.allSettled(this.promises);
127
+ if (!this.snapshotsList.length)
128
+ return;
129
+ const snapshots = this.snapshotsList.reduce((acc, group, index) => {
130
+ const block = this.snapshots[group || index].reduce((acc, [content, name]) => {
131
+ name = `## ${name || `test: ${index}`}\n\n`;
132
+ const block = `\`\`\`javascript\n${content}\n\`\`\`\n`;
133
+ return `${acc}${name + block}\n`;
134
+ }, "");
135
+ return `${acc}# ${Number.isInteger(group) ? `Group: ${index}` : group}\n\n${block}`;
136
+ }, "");
137
+ env
138
+ .expect(snapshots)
139
+ .toMatchFileSnapshot(node_path_1.default.join(this.src, "hooks.snap.txt"), options);
140
+ }
141
+ }
142
+ exports.HookCasesContext = HookCasesContext;
143
+ class HookTaskProcessor extends snapshot_1.SnapshotProcessor {
144
+ constructor(_hookOptions) {
145
+ super({
146
+ defaultOptions: (HookTaskProcessor.defaultOptions),
147
+ ..._hookOptions
148
+ });
149
+ this._hookOptions = _hookOptions;
150
+ }
151
+ async config(context) {
152
+ await super.config(context);
153
+ const compiler = this.getCompiler(context);
154
+ if (typeof this._hookOptions.options === "function") {
155
+ compiler.mergeOptions(this._hookOptions.options(context));
156
+ }
157
+ }
158
+ async compiler(context) {
159
+ await super.compiler(context);
160
+ if (typeof this._hookOptions.compiler === "function") {
161
+ const compiler = this.getCompiler(context);
162
+ await this._hookOptions.compiler(context, compiler.getCompiler());
163
+ }
164
+ }
165
+ async check(env, context) {
166
+ await context.collectSnapshots(env);
167
+ await super.check(env, context);
168
+ if (typeof this._hookOptions.check === "function") {
169
+ await this._hookOptions.check(context);
170
+ }
171
+ }
172
+ static defaultOptions(context) {
173
+ return {
174
+ context: context.getSource(),
175
+ mode: "production",
176
+ target: "async-node",
177
+ devtool: false,
178
+ cache: false,
179
+ entry: "./hook",
180
+ output: {
181
+ path: context.getDist()
182
+ },
183
+ optimization: {
184
+ minimize: false
185
+ },
186
+ experiments: {
187
+ css: true,
188
+ rspackFuture: {
189
+ bundlerInfo: {
190
+ force: false
191
+ }
192
+ }
193
+ }
194
+ };
195
+ }
196
+ static overrideOptions(options) {
197
+ if (!global.printLogger) {
198
+ options.infrastructureLogging = {
199
+ level: "error"
200
+ };
201
+ }
202
+ }
203
+ }
204
+ exports.HookTaskProcessor = HookTaskProcessor;
@@ -0,0 +1,14 @@
1
+ import { ECompilerType, type ITestContext, type ITestEnv, type TCompilerOptions } from "../type";
2
+ import type { IBasicProcessorOptions } from "./basic";
3
+ import { HotProcessor } from "./hot";
4
+ export interface IHotNewIncrementalProcessorOptions<T extends ECompilerType> extends Omit<IBasicProcessorOptions<T>, "runable"> {
5
+ target: TCompilerOptions<T>["target"];
6
+ webpackCases: boolean;
7
+ }
8
+ export declare class HotNewIncrementalProcessor<T extends ECompilerType> extends HotProcessor<T> {
9
+ protected _hotOptions: IHotNewIncrementalProcessorOptions<T>;
10
+ constructor(_hotOptions: IHotNewIncrementalProcessorOptions<T>);
11
+ run(env: ITestEnv, context: ITestContext): Promise<void>;
12
+ afterAll(context: ITestContext): Promise<void>;
13
+ static defaultOptions<T extends ECompilerType>(this: HotNewIncrementalProcessor<T>, context: ITestContext): TCompilerOptions<T>;
14
+ }
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.HotNewIncrementalProcessor = void 0;
4
+ const type_1 = require("../type");
5
+ const hot_1 = require("./hot");
6
+ class HotNewIncrementalProcessor extends hot_1.HotProcessor {
7
+ constructor(_hotOptions) {
8
+ super({
9
+ defaultOptions: HotNewIncrementalProcessor.defaultOptions,
10
+ ..._hotOptions
11
+ });
12
+ this._hotOptions = _hotOptions;
13
+ }
14
+ async run(env, context) {
15
+ context.setValue(this._options.name, "documentType", this._hotOptions.webpackCases ? type_1.EDocumentType.Fake : type_1.EDocumentType.JSDOM);
16
+ await super.run(env, context);
17
+ }
18
+ async afterAll(context) {
19
+ try {
20
+ await super.afterAll(context);
21
+ }
22
+ catch (e) {
23
+ const isFake = context.getValue(this._options.name, "documentType") ===
24
+ type_1.EDocumentType.Fake;
25
+ if (isFake && /Should run all hot steps/.test(e.message))
26
+ return;
27
+ throw e;
28
+ }
29
+ }
30
+ static defaultOptions(context) {
31
+ const options = super.defaultOptions(context);
32
+ if (this._hotOptions.compilerType === type_1.ECompilerType.Rspack) {
33
+ const rspackOptions = options;
34
+ rspackOptions.experiments ??= {};
35
+ rspackOptions.experiments.incremental ??= "advance-silent";
36
+ }
37
+ else {
38
+ throw new Error("HotNewIncrementalProcessor should only used for Rspack.");
39
+ }
40
+ return options;
41
+ }
42
+ }
43
+ exports.HotNewIncrementalProcessor = HotNewIncrementalProcessor;
@@ -0,0 +1,18 @@
1
+ import type { THotStepRuntimeData } from "../runner";
2
+ import type { ECompilerType, ITestContext, ITestEnv, TCompilerOptions, TCompilerStatsCompilation } from "../type";
3
+ import { HotProcessor, type IHotProcessorOptions } from "./hot";
4
+ type TModuleGetHandler = (file: string, options: TCompilerOptions<ECompilerType>) => string[];
5
+ export interface IHotSnapshotProcessorOptions<T extends ECompilerType> extends IHotProcessorOptions<T> {
6
+ getModuleHandler?: TModuleGetHandler;
7
+ snapshot?: string;
8
+ }
9
+ export declare class HotSnapshotProcessor<T extends ECompilerType> extends HotProcessor<T> {
10
+ protected _hotOptions: IHotSnapshotProcessorOptions<T>;
11
+ private hashes;
12
+ private entries;
13
+ constructor(_hotOptions: IHotSnapshotProcessorOptions<T>);
14
+ run(env: ITestEnv, context: ITestContext): Promise<void>;
15
+ check(env: ITestEnv, context: ITestContext): Promise<void>;
16
+ protected matchStepSnapshot(env: ITestEnv, context: ITestContext, step: number, stats: TCompilerStatsCompilation<T>, runtime?: THotStepRuntimeData): void;
17
+ }
18
+ export {};
@@ -0,0 +1,299 @@
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.HotSnapshotProcessor = void 0;
7
+ const node_path_1 = __importDefault(require("node:path"));
8
+ const fs_extra_1 = __importDefault(require("fs-extra"));
9
+ const placeholder_1 = require("../helper/expect/placeholder");
10
+ const win_1 = require("../helper/win");
11
+ const hot_1 = require("./hot");
12
+ const NOOP_SET = new Set();
13
+ const escapeLocalName = (str) => str.split(/[-<>:"/|?*.]/).join("_");
14
+ const SELF_HANDLER = (file, options) => {
15
+ let res = [];
16
+ const hotUpdateGlobal = (_, modules) => {
17
+ res = Object.keys(modules);
18
+ };
19
+ const hotUpdateGlobalKey = escapeLocalName(`${options.output?.hotUpdateGlobal || "webpackHotUpdate"}${options.output?.uniqueName || ""}`);
20
+ global.self ??= {};
21
+ global.self[hotUpdateGlobalKey] = hotUpdateGlobal;
22
+ require(file);
23
+ delete global.self[hotUpdateGlobalKey];
24
+ if (!Object.keys(global.self).length) {
25
+ delete global.self;
26
+ }
27
+ return res;
28
+ };
29
+ const NODE_HANDLER = (file) => {
30
+ return Object.keys(require(file).modules) || [];
31
+ };
32
+ const GET_MODULE_HANDLER = {
33
+ web: SELF_HANDLER,
34
+ webworker: SELF_HANDLER,
35
+ "async-node": NODE_HANDLER,
36
+ node: NODE_HANDLER
37
+ };
38
+ class HotSnapshotProcessor extends hot_1.HotProcessor {
39
+ constructor(_hotOptions) {
40
+ super(_hotOptions);
41
+ this._hotOptions = _hotOptions;
42
+ this.hashes = [];
43
+ this.entries = {};
44
+ }
45
+ async run(env, context) {
46
+ context.setValue(this._options.name, "hotUpdateStepChecker", (hotUpdateContext, stats, runtime) => {
47
+ const statsJson = stats.toJson({
48
+ assets: true,
49
+ chunks: true
50
+ });
51
+ const chunks = Array.from(
52
+ // Some chunk fields are missing from rspack
53
+ stats?.compilation.chunks || NOOP_SET);
54
+ for (const entry of chunks.filter(i => i.hasRuntime())) {
55
+ if (!this.entries[entry.id] && entry.runtime) {
56
+ this.entries[entry.id] =
57
+ // Webpack uses `string | SortableSet<string>` for `entry.runtime`
58
+ typeof entry.runtime === "string"
59
+ ? [entry.runtime]
60
+ : Array.from(entry.runtime);
61
+ }
62
+ }
63
+ this.matchStepSnapshot(env, context, hotUpdateContext.updateIndex, statsJson, runtime);
64
+ this.hashes.push(stats.hash);
65
+ });
66
+ context.setValue(this._options.name, "hotUpdateStepErrorChecker", (_, stats, runtime) => {
67
+ this.hashes.push(stats.hash);
68
+ });
69
+ await super.run(env, context);
70
+ }
71
+ async check(env, context) {
72
+ const compiler = this.getCompiler(context);
73
+ const stats = compiler.getStats();
74
+ if (!stats || !stats.hash) {
75
+ env.expect(false);
76
+ return;
77
+ }
78
+ const statsJson = stats.toJson({ assets: true, chunks: true });
79
+ const chunks = Array.from(
80
+ // Some chunk fields are missing from rspack
81
+ stats?.compilation.chunks || NOOP_SET);
82
+ for (const entry of chunks.filter(i => i.hasRuntime())) {
83
+ if (entry.runtime) {
84
+ this.entries[entry.id] =
85
+ // Webpack uses `string | SortableSet<string>` for `entry.runtime`
86
+ typeof entry.runtime === "string"
87
+ ? [entry.runtime]
88
+ : Array.from(entry.runtime);
89
+ }
90
+ }
91
+ let matchFailed = null;
92
+ try {
93
+ this.matchStepSnapshot(env, context, 0, statsJson);
94
+ }
95
+ catch (e) {
96
+ matchFailed = e;
97
+ }
98
+ this.hashes.push(stats.hash);
99
+ if (matchFailed) {
100
+ throw matchFailed;
101
+ }
102
+ }
103
+ matchStepSnapshot(env, context, step, stats, runtime) {
104
+ const compiler = this.getCompiler(context);
105
+ const compilerOptions = compiler.getOptions();
106
+ const getModuleHandler = this._hotOptions.getModuleHandler ||
107
+ GET_MODULE_HANDLER[compilerOptions.target];
108
+ env.expect(typeof getModuleHandler).toBe("function");
109
+ const lastHash = this.hashes[this.hashes.length - 1];
110
+ const snapshotPath = context.getSource(`${this._hotOptions.snapshot || `__snapshots__/${compilerOptions.target}`}/${step}.snap.txt`);
111
+ const title = `Case ${node_path_1.default.basename(this._options.name)}: Step ${step}`;
112
+ const hotUpdateFile = [];
113
+ const hotUpdateManifest = [];
114
+ const changedFiles = this.updateOptions.updateIndex === 0
115
+ ? []
116
+ : this.updateOptions.changedFiles.map((i) => (0, win_1.escapeSep)(node_path_1.default.relative(context.getSource(), i)));
117
+ changedFiles.sort();
118
+ const hashes = {
119
+ [lastHash || "LAST_HASH"]: "LAST_HASH",
120
+ [stats.hash]: "CURRENT_HASH"
121
+ };
122
+ // TODO: find a better way
123
+ // replace [runtime] to [runtime of id] to prevent worker hash
124
+ const runtimes = {};
125
+ for (const [id, runtime] of Object.entries(this.entries)) {
126
+ if (typeof runtime === "string") {
127
+ if (runtime !== id) {
128
+ runtimes[runtime] = `[runtime of ${id}]`;
129
+ }
130
+ }
131
+ else if (Array.isArray(runtime)) {
132
+ for (const r of runtime) {
133
+ if (r !== id) {
134
+ runtimes[r] = `[runtime of ${id}]`;
135
+ }
136
+ }
137
+ }
138
+ }
139
+ const replaceContent = (str) => {
140
+ return (0, placeholder_1.normalizePlaceholder)(Object.entries(hashes)
141
+ .reduce((str, [raw, replacement]) => {
142
+ return str.split(raw).join(replacement);
143
+ }, str)
144
+ .replace(/\/\/ (\d+)\s+(?=var cssReload)/, ""));
145
+ };
146
+ const replaceFileName = (str) => {
147
+ return Object.entries({
148
+ ...hashes,
149
+ ...runtimes
150
+ }).reduce((str, [raw, replacement]) => {
151
+ return str.split(raw).join(replacement);
152
+ }, str);
153
+ };
154
+ const fileList = stats
155
+ .assets.map(i => {
156
+ const fileName = i.name;
157
+ const renderName = replaceFileName(fileName);
158
+ const content = replaceContent(fs_extra_1.default.readFileSync(context.getDist(fileName), "utf-8"));
159
+ if (fileName.endsWith("hot-update.js")) {
160
+ const modules = getModuleHandler(context.getDist(fileName), compilerOptions);
161
+ const runtime = [];
162
+ for (const i of content.matchAll(/\/\/ (webpack\/runtime\/[\w_-]+)\s*\n/g)) {
163
+ runtime.push(i[1]);
164
+ }
165
+ modules.sort();
166
+ runtime.sort();
167
+ hotUpdateFile.push({
168
+ name: renderName,
169
+ content,
170
+ modules,
171
+ runtime
172
+ });
173
+ return `- Update: ${renderName}, size: ${content.length}`;
174
+ }
175
+ if (fileName.endsWith("hot-update.json")) {
176
+ const manifest = JSON.parse(content);
177
+ manifest.c?.sort();
178
+ manifest.r?.sort();
179
+ manifest.m?.sort();
180
+ hotUpdateManifest.push({
181
+ name: renderName,
182
+ content: JSON.stringify(manifest)
183
+ });
184
+ return `- Manifest: ${renderName}, size: ${i.size}`;
185
+ }
186
+ if (fileName.endsWith(".js")) {
187
+ return `- Bundle: ${renderName}`;
188
+ }
189
+ })
190
+ .filter(Boolean);
191
+ fileList.sort();
192
+ hotUpdateManifest.sort((a, b) => (a.name > b.name ? 1 : -1));
193
+ hotUpdateFile.sort((a, b) => (a.name > b.name ? 1 : -1));
194
+ if (runtime?.javascript) {
195
+ runtime.javascript.outdatedModules.sort();
196
+ runtime.javascript.updatedModules.sort();
197
+ runtime.javascript.updatedRuntime.sort();
198
+ runtime.javascript.acceptedModules.sort();
199
+ runtime.javascript.disposedModules.sort();
200
+ for (const value of Object.values(runtime.javascript.outdatedDependencies)) {
201
+ value.sort();
202
+ }
203
+ }
204
+ const content = `
205
+ # ${title}
206
+
207
+ ## Changed Files
208
+ ${changedFiles.map(i => `- ${i}`).join("\n")}
209
+
210
+ ## Asset Files
211
+ ${fileList.join("\n")}
212
+
213
+ ## Manifest
214
+ ${hotUpdateManifest
215
+ .map(i => `
216
+ ### ${i.name}
217
+
218
+ \`\`\`json
219
+ ${i.content}
220
+ \`\`\`
221
+ `)
222
+ .join("\n\n")}
223
+
224
+ ## Update
225
+
226
+ ${hotUpdateFile
227
+ .map(i => `
228
+ ### ${i.name}
229
+
230
+ #### Changed Modules
231
+ ${i.modules.map(i => `- ${i}`).join("\n")}
232
+
233
+ #### Changed Runtime Modules
234
+ ${i.runtime.map(i => `- ${i}`).join("\n")}
235
+
236
+ #### Changed Content
237
+ \`\`\`js
238
+ ${i.content}
239
+ \`\`\`
240
+ `)
241
+ .join("\n\n")}
242
+
243
+
244
+ ${runtime
245
+ ? `
246
+ ## Runtime
247
+ ### Status
248
+
249
+ \`\`\`txt
250
+ ${runtime.statusPath.join(" => ")}
251
+ \`\`\`
252
+
253
+ ${runtime.javascript
254
+ ? `
255
+
256
+ ### JavaScript
257
+
258
+ #### Outdated
259
+
260
+ Outdated Modules:
261
+ ${runtime.javascript.outdatedModules.map(i => `- ${i}`).join("\n")}
262
+
263
+
264
+ Outdated Dependencies:
265
+ \`\`\`json
266
+ ${JSON.stringify(runtime.javascript.outdatedDependencies || {}, null, 2)}
267
+ \`\`\`
268
+
269
+ #### Updated
270
+
271
+ Updated Modules:
272
+ ${runtime.javascript.updatedModules.map(i => `- ${i}`).join("\n")}
273
+
274
+ Updated Runtime:
275
+ ${runtime.javascript.updatedRuntime.map(i => `- \`${i}\``).join("\n")}
276
+
277
+
278
+ #### Callback
279
+
280
+ Accepted Callback:
281
+ ${runtime.javascript.acceptedModules.map(i => `- ${i}`).join("\n")}
282
+
283
+ Disposed Callback:
284
+ ${runtime.javascript.disposedModules.map(i => `- ${i}`).join("\n")}
285
+ `
286
+ : ""}
287
+
288
+ `
289
+ : ""}
290
+
291
+ `
292
+ .replaceAll(/%3A(\d+)%2F/g, (match, capture) => {
293
+ return match.replace(capture, "PORT");
294
+ })
295
+ .trim();
296
+ env.expect(content).toMatchFileSnapshot(snapshotPath);
297
+ }
298
+ }
299
+ exports.HotSnapshotProcessor = HotSnapshotProcessor;
@@ -0,0 +1,17 @@
1
+ import { ECompilerType, type ITestContext, type ITestEnv, type ITestRunner, type TCompilerOptions, type TUpdateOptions } from "../type";
2
+ import { BasicProcessor, type IBasicProcessorOptions } from "./basic";
3
+ export interface IHotProcessorOptions<T extends ECompilerType> extends Omit<IBasicProcessorOptions<T>, "runable"> {
4
+ target: TCompilerOptions<T>["target"];
5
+ checkSteps?: boolean;
6
+ }
7
+ export declare class HotProcessor<T extends ECompilerType> extends BasicProcessor<T> {
8
+ protected _hotOptions: IHotProcessorOptions<T>;
9
+ protected updateOptions: TUpdateOptions;
10
+ protected runner: ITestRunner | null;
11
+ constructor(_hotOptions: IHotProcessorOptions<T>);
12
+ run(env: ITestEnv, context: ITestContext): Promise<void>;
13
+ static findBundle<T extends ECompilerType>(this: HotProcessor<T>, context: ITestContext): string[];
14
+ afterAll(context: ITestContext): Promise<void>;
15
+ static defaultOptions<T extends ECompilerType>(this: HotProcessor<T>, context: ITestContext): TCompilerOptions<T>;
16
+ static overrideOptions<T extends ECompilerType>(this: HotProcessor<T>, context: ITestContext, options: TCompilerOptions<T>): void;
17
+ }