@rspack/test-tools 1.2.7-alpha.0 → 1.2.8
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/dist/case/builtin.js +2 -1
- package/dist/case/cache.js +2 -1
- package/dist/case/config.js +2 -1
- package/dist/case/diagnostic.js +2 -1
- package/dist/case/diff.js +1 -2
- package/dist/case/hot-step.js +2 -1
- package/dist/case/hot.js +2 -1
- package/dist/case/index.d.ts +1 -0
- package/dist/case/index.js +1 -0
- package/dist/case/new-code-splitting.js +2 -1
- package/dist/case/new-incremental.js +4 -2
- package/dist/case/normal.js +2 -1
- package/dist/case/serial.d.ts +3 -0
- package/dist/case/serial.js +34 -0
- package/dist/case/watch.js +2 -1
- package/dist/compiler.js +4 -0
- package/dist/helper/expect/to-match-file-snapshot.d.ts +1 -1
- package/dist/helper/expect/to-match-file-snapshot.js +5 -1
- package/dist/helper/util/currentWatchStep.d.ts +1 -1
- package/dist/helper/util/currentWatchStep.js +1 -1
- package/dist/processor/config.js +5 -0
- package/dist/processor/hot.js +5 -0
- package/dist/processor/watch.js +10 -3
- package/dist/runner/runner/cjs.d.ts +3 -0
- package/dist/runner/runner/cjs.js +37 -1
- package/dist/runner/runner/web/jsdom.d.ts +8 -1
- package/dist/runner/runner/web/jsdom.js +64 -41
- package/dist/runner/type.d.ts +2 -2
- package/dist/test/creator.d.ts +17 -0
- package/dist/test/creator.js +179 -3
- package/dist/type.d.ts +2 -1
- package/package.json +13 -13
package/dist/case/builtin.js
CHANGED
package/dist/case/cache.js
CHANGED
package/dist/case/config.js
CHANGED
|
@@ -27,7 +27,8 @@ const creator = new creator_1.BasicCaseCreator({
|
|
|
27
27
|
configFiles: ["rspack.config.js", "webpack.config.js"]
|
|
28
28
|
})
|
|
29
29
|
],
|
|
30
|
-
runner: runner_1.MultipleRunnerFactory
|
|
30
|
+
runner: runner_1.MultipleRunnerFactory,
|
|
31
|
+
concurrent: 3
|
|
31
32
|
});
|
|
32
33
|
function createConfigCase(name, src, dist) {
|
|
33
34
|
creator.create(name, src, dist);
|
package/dist/case/diagnostic.js
CHANGED
package/dist/case/diff.js
CHANGED
|
@@ -33,11 +33,10 @@ function createDiffCase(name, src, dist) {
|
|
|
33
33
|
steps: [processor]
|
|
34
34
|
});
|
|
35
35
|
(0, rimraf_1.rimrafSync)(dist);
|
|
36
|
-
const buildTask = tester.compile();
|
|
37
36
|
const prefix = node_path_1.default.basename(name);
|
|
38
37
|
describe(`${prefix}:check`, () => {
|
|
39
38
|
beforeAll(async () => {
|
|
40
|
-
await
|
|
39
|
+
await tester.compile();
|
|
41
40
|
compareMap.clear();
|
|
42
41
|
await tester.check(env);
|
|
43
42
|
});
|
package/dist/case/hot-step.js
CHANGED
package/dist/case/hot.js
CHANGED
package/dist/case/index.d.ts
CHANGED
package/dist/case/index.js
CHANGED
|
@@ -33,7 +33,8 @@ const configCreator = new creator_1.BasicCaseCreator({
|
|
|
33
33
|
configFiles: ["rspack.config.js", "webpack.config.js"]
|
|
34
34
|
});
|
|
35
35
|
return [processor];
|
|
36
|
-
}
|
|
36
|
+
},
|
|
37
|
+
concurrent: 3
|
|
37
38
|
});
|
|
38
39
|
class NewCodeSplittingProcessor extends processor_1.ConfigProcessor {
|
|
39
40
|
constructor(_configOptions) {
|
|
@@ -29,7 +29,8 @@ function getHotCreator(target, documentType) {
|
|
|
29
29
|
documentType
|
|
30
30
|
})
|
|
31
31
|
],
|
|
32
|
-
runner: runner_1.HotRunnerFactory
|
|
32
|
+
runner: runner_1.HotRunnerFactory,
|
|
33
|
+
concurrent: true
|
|
33
34
|
}));
|
|
34
35
|
}
|
|
35
36
|
return hotCreators.get(key);
|
|
@@ -76,7 +77,8 @@ const watchCreator = new creator_1.BasicCaseCreator({
|
|
|
76
77
|
compilerType: type_1.ECompilerType.Rspack,
|
|
77
78
|
configFiles: ["rspack.config.js", "webpack.config.js"]
|
|
78
79
|
}, watchState));
|
|
79
|
-
}
|
|
80
|
+
},
|
|
81
|
+
concurrent: true
|
|
80
82
|
});
|
|
81
83
|
function createWatchNewIncrementalCase(name, src, dist, temp) {
|
|
82
84
|
watchCreator.create(name, src, dist, temp);
|
package/dist/case/normal.js
CHANGED
|
@@ -21,7 +21,8 @@ const creator = new creator_1.BasicCaseCreator({
|
|
|
21
21
|
compilerType: type_1.ECompilerType.Rspack
|
|
22
22
|
})
|
|
23
23
|
],
|
|
24
|
-
runner: runner_1.NormalRunnerFactory
|
|
24
|
+
runner: runner_1.NormalRunnerFactory,
|
|
25
|
+
concurrent: true
|
|
25
26
|
});
|
|
26
27
|
function createNormalCase(name, src, dist) {
|
|
27
28
|
creator.create(name, src, dist);
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createSerialCase = createSerialCase;
|
|
4
|
+
const config_1 = require("../processor/config");
|
|
5
|
+
const runner_1 = require("../runner");
|
|
6
|
+
const creator_1 = require("../test/creator");
|
|
7
|
+
const type_1 = require("../type");
|
|
8
|
+
const creator = new creator_1.BasicCaseCreator({
|
|
9
|
+
clean: true,
|
|
10
|
+
describe: false,
|
|
11
|
+
testConfig: testConfig => {
|
|
12
|
+
const oldModuleScope = testConfig.moduleScope;
|
|
13
|
+
testConfig.moduleScope = (ms, stats) => {
|
|
14
|
+
let res = ms;
|
|
15
|
+
// TODO: modify runner module scope based on stats here
|
|
16
|
+
if (typeof oldModuleScope === "function") {
|
|
17
|
+
res = oldModuleScope(ms, stats);
|
|
18
|
+
}
|
|
19
|
+
return res;
|
|
20
|
+
};
|
|
21
|
+
},
|
|
22
|
+
steps: ({ name }) => [
|
|
23
|
+
new config_1.ConfigProcessor({
|
|
24
|
+
name,
|
|
25
|
+
runable: true,
|
|
26
|
+
compilerType: type_1.ECompilerType.Rspack,
|
|
27
|
+
configFiles: ["rspack.config.js", "webpack.config.js"]
|
|
28
|
+
})
|
|
29
|
+
],
|
|
30
|
+
runner: runner_1.MultipleRunnerFactory
|
|
31
|
+
});
|
|
32
|
+
function createSerialCase(name, src, dist) {
|
|
33
|
+
creator.create(name, src, dist);
|
|
34
|
+
}
|
package/dist/case/watch.js
CHANGED
|
@@ -45,7 +45,8 @@ const creator = new creator_1.BasicCaseCreator({
|
|
|
45
45
|
compilerType: type_1.ECompilerType.Rspack,
|
|
46
46
|
configFiles: ["rspack.config.js", "webpack.config.js"]
|
|
47
47
|
}, watchState));
|
|
48
|
-
}
|
|
48
|
+
},
|
|
49
|
+
concurrent: true
|
|
49
50
|
});
|
|
50
51
|
function createWatchCase(name, src, dist, temp) {
|
|
51
52
|
creator.create(name, src, dist, temp);
|
package/dist/compiler.js
CHANGED
|
@@ -65,6 +65,10 @@ class TestCompilerManager {
|
|
|
65
65
|
if (!this.compilerInstance)
|
|
66
66
|
throw new Error("Compiler should be created before watch");
|
|
67
67
|
this.compilerInstance.watch({
|
|
68
|
+
// IMPORTANT:
|
|
69
|
+
// This is a workaround for the issue that watchpack cannot detect the file change in time
|
|
70
|
+
// so we set the poll to 300ms to make it more sensitive to the file change
|
|
71
|
+
poll: 300,
|
|
68
72
|
aggregateTimeout: timeout
|
|
69
73
|
}, (error, newStats) => {
|
|
70
74
|
this.emitter.emit(ECompilerEvent.Build, error, newStats);
|
|
@@ -17,7 +17,7 @@ export declare function toMatchFileSnapshot(this: {
|
|
|
17
17
|
unmatched: number;
|
|
18
18
|
_updateSnapshot: "none" | "new" | "all";
|
|
19
19
|
};
|
|
20
|
-
},
|
|
20
|
+
}, rawContent: string | Buffer, filepath: string, options?: FileMatcherOptions): {
|
|
21
21
|
pass: boolean;
|
|
22
22
|
message: () => string;
|
|
23
23
|
};
|
|
@@ -11,6 +11,7 @@ const node_path_1 = __importDefault(require("node:path"));
|
|
|
11
11
|
const chalk_1 = __importDefault(require("chalk"));
|
|
12
12
|
const filenamify_1 = __importDefault(require("filenamify"));
|
|
13
13
|
const jest_diff_1 = require("jest-diff");
|
|
14
|
+
const { serialize } = require(node_path_1.default.join(node_path_1.default.dirname(require.resolve("jest-snapshot")), "./utils.js"));
|
|
14
15
|
/**
|
|
15
16
|
* Check if 2 strings or buffer are equal
|
|
16
17
|
*/
|
|
@@ -25,7 +26,10 @@ const isEqual = (a, b) => {
|
|
|
25
26
|
* @param filepath Path to the file to match against
|
|
26
27
|
* @param options Additional options for matching
|
|
27
28
|
*/
|
|
28
|
-
function toMatchFileSnapshot(
|
|
29
|
+
function toMatchFileSnapshot(rawContent, filepath, options = {}) {
|
|
30
|
+
const content = Buffer.isBuffer(rawContent) || typeof rawContent === "string"
|
|
31
|
+
? rawContent
|
|
32
|
+
: serialize(rawContent);
|
|
29
33
|
const { isNot, snapshotState } = this;
|
|
30
34
|
const filename = filepath === undefined
|
|
31
35
|
? // If file name is not specified, generate one from the test title
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export const step: {};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
exports.step =
|
|
2
|
+
exports.step = {};
|
package/dist/processor/config.js
CHANGED
|
@@ -71,6 +71,11 @@ class ConfigProcessor extends multi_1.MultiTaskProcessor {
|
|
|
71
71
|
options.output ??= {};
|
|
72
72
|
options.output.filename = `bundle${index}${outputModule ? ".mjs" : ".js"}`;
|
|
73
73
|
}
|
|
74
|
+
if (!global.printLogger) {
|
|
75
|
+
options.infrastructureLogging = {
|
|
76
|
+
level: "error"
|
|
77
|
+
};
|
|
78
|
+
}
|
|
74
79
|
}
|
|
75
80
|
}
|
|
76
81
|
exports.ConfigProcessor = ConfigProcessor;
|
package/dist/processor/hot.js
CHANGED
|
@@ -121,6 +121,11 @@ class HotProcessor extends basic_1.BasicProcessor {
|
|
|
121
121
|
options.plugins ??= [];
|
|
122
122
|
options.plugins.push(new core_1.rspack.LoaderOptionsPlugin(this.updateOptions));
|
|
123
123
|
}
|
|
124
|
+
if (!global.printLogger) {
|
|
125
|
+
options.infrastructureLogging = {
|
|
126
|
+
level: "error"
|
|
127
|
+
};
|
|
128
|
+
}
|
|
124
129
|
}
|
|
125
130
|
}
|
|
126
131
|
exports.HotProcessor = HotProcessor;
|
package/dist/processor/watch.js
CHANGED
|
@@ -36,7 +36,8 @@ class WatchProcessor extends multi_1.MultiTaskProcessor {
|
|
|
36
36
|
async build(context) {
|
|
37
37
|
const compiler = this.getCompiler(context);
|
|
38
38
|
const currentWatchStepModule = require(currentWatchStepModulePath);
|
|
39
|
-
currentWatchStepModule.step
|
|
39
|
+
currentWatchStepModule.step[this._options.name] =
|
|
40
|
+
this._watchOptions.stepName;
|
|
40
41
|
node_fs_1.default.mkdirSync(this._watchOptions.tempDir, { recursive: true });
|
|
41
42
|
(0, copyDiff_1.default)(node_path_1.default.join(context.getSource(), this._watchOptions.stepName), this._watchOptions.tempDir, true);
|
|
42
43
|
const task = new Promise((resolve, reject) => {
|
|
@@ -173,7 +174,7 @@ class WatchProcessor extends multi_1.MultiTaskProcessor {
|
|
|
173
174
|
if (!options.output.path)
|
|
174
175
|
options.output.path = context.getDist();
|
|
175
176
|
if (typeof options.output.pathinfo === "undefined")
|
|
176
|
-
options.output.pathinfo =
|
|
177
|
+
options.output.pathinfo = false;
|
|
177
178
|
if (!options.output.filename)
|
|
178
179
|
options.output.filename = "bundle.js";
|
|
179
180
|
if (options.cache && options.cache.type === "filesystem") {
|
|
@@ -203,6 +204,11 @@ class WatchProcessor extends multi_1.MultiTaskProcessor {
|
|
|
203
204
|
options.experiments.rspackFuture ??= {};
|
|
204
205
|
options.experiments.rspackFuture.bundlerInfo ??= {};
|
|
205
206
|
options.experiments.rspackFuture.bundlerInfo.force ??= false;
|
|
207
|
+
if (!global.printLogger) {
|
|
208
|
+
options.infrastructureLogging = {
|
|
209
|
+
level: "error"
|
|
210
|
+
};
|
|
211
|
+
}
|
|
206
212
|
};
|
|
207
213
|
}
|
|
208
214
|
static findBundle(index, context, options) {
|
|
@@ -226,7 +232,8 @@ class WatchStepProcessor extends WatchProcessor {
|
|
|
226
232
|
async build(context) {
|
|
227
233
|
const compiler = this.getCompiler(context);
|
|
228
234
|
const currentWatchStepModule = require(currentWatchStepModulePath);
|
|
229
|
-
currentWatchStepModule.step
|
|
235
|
+
currentWatchStepModule.step[this._options.name] =
|
|
236
|
+
this._watchOptions.stepName;
|
|
230
237
|
const task = new Promise((resolve, reject) => {
|
|
231
238
|
compiler.getEmitter().once(compiler_1.ECompilerEvent.Build, (e, stats) => {
|
|
232
239
|
if (e)
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import type { ECompilerType } from "../../type";
|
|
2
2
|
import type { IBasicGlobalContext, IBasicModuleScope, TBasicRunnerFile, TModuleObject, TRunnerRequirer } from "../type";
|
|
3
3
|
import { BasicRunner } from "./basic";
|
|
4
|
+
declare global {
|
|
5
|
+
var printLogger: boolean;
|
|
6
|
+
}
|
|
4
7
|
export declare class CommonJsRunner<T extends ECompilerType = ECompilerType.Rspack> extends BasicRunner<T> {
|
|
5
8
|
protected createGlobalContext(): IBasicGlobalContext;
|
|
6
9
|
protected createBaseModuleScope(): IBasicModuleScope;
|
|
@@ -14,7 +14,42 @@ const define = (...args) => {
|
|
|
14
14
|
class CommonJsRunner extends basic_1.BasicRunner {
|
|
15
15
|
createGlobalContext() {
|
|
16
16
|
return {
|
|
17
|
-
console:
|
|
17
|
+
console: {
|
|
18
|
+
log: (...args) => {
|
|
19
|
+
if (printLogger) {
|
|
20
|
+
console.log(...args);
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
warn: (...args) => {
|
|
24
|
+
if (printLogger) {
|
|
25
|
+
console.warn(...args);
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
error: (...args) => {
|
|
29
|
+
console.error(...args);
|
|
30
|
+
},
|
|
31
|
+
info: (...args) => {
|
|
32
|
+
if (printLogger) {
|
|
33
|
+
console.info(...args);
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
debug: (...args) => {
|
|
37
|
+
if (printLogger) {
|
|
38
|
+
console.info(...args);
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
trace: (...args) => {
|
|
42
|
+
if (printLogger) {
|
|
43
|
+
console.info(...args);
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
assert: (...args) => {
|
|
47
|
+
console.assert(...args);
|
|
48
|
+
},
|
|
49
|
+
clear: () => {
|
|
50
|
+
console.clear();
|
|
51
|
+
}
|
|
52
|
+
},
|
|
18
53
|
setTimeout: ((cb, ms, ...args) => {
|
|
19
54
|
const timeout = setTimeout(cb, ms, ...args);
|
|
20
55
|
timeout.unref();
|
|
@@ -34,6 +69,7 @@ class CommonJsRunner extends basic_1.BasicRunner {
|
|
|
34
69
|
});
|
|
35
70
|
return m;
|
|
36
71
|
},
|
|
72
|
+
__SNAPSHOT__: node_path_1.default.join(this._options.source, "__snapshot__"),
|
|
37
73
|
...this._options.env
|
|
38
74
|
};
|
|
39
75
|
return baseModuleScope;
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import type { ECompilerType } from "../../../type";
|
|
2
|
-
import type { TRunnerRequirer } from "../../type";
|
|
2
|
+
import type { TBasicRunnerFile, TRunnerRequirer } from "../../type";
|
|
3
3
|
import type { IBasicRunnerOptions } from "../basic";
|
|
4
4
|
import { CommonJsRunner } from "../cjs";
|
|
5
5
|
export declare class JSDOMWebRunner<T extends ECompilerType = ECompilerType.Rspack> extends CommonJsRunner<T> {
|
|
6
6
|
protected _webOptions: IBasicRunnerOptions<T>;
|
|
7
7
|
private dom;
|
|
8
|
+
private requireCache;
|
|
8
9
|
constructor(_webOptions: IBasicRunnerOptions<T>);
|
|
9
10
|
run(file: string): Promise<unknown>;
|
|
10
11
|
getGlobal(name: string): unknown;
|
|
@@ -14,6 +15,12 @@ export declare class JSDOMWebRunner<T extends ECompilerType = ECompilerType.Rspa
|
|
|
14
15
|
}): any;
|
|
15
16
|
};
|
|
16
17
|
protected createBaseModuleScope(): import("../../type").IBasicModuleScope;
|
|
18
|
+
protected getModuleContent(file: TBasicRunnerFile): [
|
|
19
|
+
{
|
|
20
|
+
exports: Record<string, unknown>;
|
|
21
|
+
},
|
|
22
|
+
string
|
|
23
|
+
];
|
|
17
24
|
protected createJSDOMRequirer(): TRunnerRequirer;
|
|
18
25
|
protected createRunner(): void;
|
|
19
26
|
}
|
|
@@ -12,10 +12,13 @@ const EventSourceForNode_1 = __importDefault(require("../../../helper/legacy/Eve
|
|
|
12
12
|
const createFakeWorker_1 = __importDefault(require("../../../helper/legacy/createFakeWorker"));
|
|
13
13
|
const urlToRelativePath_1 = __importDefault(require("../../../helper/legacy/urlToRelativePath"));
|
|
14
14
|
const cjs_1 = require("../cjs");
|
|
15
|
+
// Compatibility code to suppress iconv-lite warnings
|
|
16
|
+
require("iconv-lite").skipDecodeWarning = true;
|
|
15
17
|
class JSDOMWebRunner extends cjs_1.CommonJsRunner {
|
|
16
18
|
constructor(_webOptions) {
|
|
17
19
|
super(_webOptions);
|
|
18
20
|
this._webOptions = _webOptions;
|
|
21
|
+
this.requireCache = Object.create(null);
|
|
19
22
|
const virtualConsole = new jsdom_1.VirtualConsole();
|
|
20
23
|
virtualConsole.sendTo(console);
|
|
21
24
|
this.dom = new jsdom_1.JSDOM(`
|
|
@@ -74,10 +77,25 @@ class JSDOMWebRunner extends cjs_1.CommonJsRunner {
|
|
|
74
77
|
.resolve(this._webOptions.dist, `./${url.startsWith("https://test.cases/path/") ? url.slice(24) : url}`)
|
|
75
78
|
.split("?")[0];
|
|
76
79
|
};
|
|
80
|
+
const that = this;
|
|
77
81
|
class CustomResourceLoader extends jsdom_1.ResourceLoader {
|
|
78
82
|
fetch(url, _) {
|
|
83
|
+
const filePath = urlToPath(url);
|
|
84
|
+
let finalCode;
|
|
85
|
+
if (node_path_1.default.extname(filePath) === ".js") {
|
|
86
|
+
const currentDirectory = node_path_1.default.dirname(filePath);
|
|
87
|
+
const file = that.getFile(filePath, currentDirectory);
|
|
88
|
+
if (!file) {
|
|
89
|
+
throw new Error(`File not found: ${filePath}`);
|
|
90
|
+
}
|
|
91
|
+
const [_m, code] = that.getModuleContent(file);
|
|
92
|
+
finalCode = code;
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
finalCode = node_fs_1.default.readFileSync(filePath);
|
|
96
|
+
}
|
|
79
97
|
try {
|
|
80
|
-
return Promise.resolve(
|
|
98
|
+
return Promise.resolve(finalCode);
|
|
81
99
|
}
|
|
82
100
|
catch (err) {
|
|
83
101
|
console.error(err);
|
|
@@ -135,56 +153,61 @@ class JSDOMWebRunner extends cjs_1.CommonJsRunner {
|
|
|
135
153
|
};
|
|
136
154
|
return moduleScope;
|
|
137
155
|
}
|
|
156
|
+
getModuleContent(file) {
|
|
157
|
+
const m = {
|
|
158
|
+
exports: {}
|
|
159
|
+
};
|
|
160
|
+
const currentModuleScope = this.createModuleScope(this.getRequire(), m, file);
|
|
161
|
+
if (this._options.testConfig.moduleScope) {
|
|
162
|
+
this._options.testConfig.moduleScope(currentModuleScope);
|
|
163
|
+
}
|
|
164
|
+
const scopeKey = (0, helper_1.escapeSep)(file.path);
|
|
165
|
+
const args = Object.keys(currentModuleScope).filter(arg => !["window", "self", "globalThis", "console"].includes(arg));
|
|
166
|
+
const argValues = args
|
|
167
|
+
.map(arg => `window["${scopeKey}"]["${arg}"]`)
|
|
168
|
+
.join(", ");
|
|
169
|
+
this.dom.window[scopeKey] = currentModuleScope;
|
|
170
|
+
return [
|
|
171
|
+
m,
|
|
172
|
+
`
|
|
173
|
+
// hijack document.currentScript for auto public path
|
|
174
|
+
var $$g$$ = new Proxy(window, {
|
|
175
|
+
get(target, prop, receiver) {
|
|
176
|
+
if (prop === "document") {
|
|
177
|
+
return new Proxy(window.document, {
|
|
178
|
+
get(target, prop, receiver) {
|
|
179
|
+
if (prop === "currentScript") {
|
|
180
|
+
var script = target.createElement("script");
|
|
181
|
+
script.src = "https://test.cases/path/${(0, helper_1.escapeSep)(file.subPath)}index.js";
|
|
182
|
+
return script;
|
|
183
|
+
}
|
|
184
|
+
return Reflect.get(target, prop, receiver);
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
return Reflect.get(target, prop, receiver);
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
(function(window, self, globalThis, console, ${args.join(", ")}) {
|
|
192
|
+
${file.content}
|
|
193
|
+
})($$g$$, $$g$$, $$g$$, window["console"], ${argValues});
|
|
194
|
+
`
|
|
195
|
+
];
|
|
196
|
+
}
|
|
138
197
|
createJSDOMRequirer() {
|
|
139
|
-
const requireCache = Object.create(null);
|
|
140
198
|
return (currentDirectory, modulePath, context = {}) => {
|
|
141
199
|
const file = context.file || this.getFile(modulePath, currentDirectory);
|
|
142
200
|
if (!file) {
|
|
143
201
|
return this.requirers.get("miss")(currentDirectory, modulePath);
|
|
144
202
|
}
|
|
145
|
-
if (file.path in requireCache) {
|
|
146
|
-
return requireCache[file.path].exports;
|
|
203
|
+
if (file.path in this.requireCache) {
|
|
204
|
+
return this.requireCache[file.path].exports;
|
|
147
205
|
}
|
|
148
|
-
const m =
|
|
149
|
-
exports: {}
|
|
150
|
-
};
|
|
151
|
-
requireCache[file.path] = m;
|
|
152
|
-
const currentModuleScope = this.createModuleScope(this.getRequire(), m, file);
|
|
153
|
-
if (this._options.testConfig.moduleScope) {
|
|
154
|
-
this._options.testConfig.moduleScope(currentModuleScope);
|
|
155
|
-
}
|
|
156
|
-
const scopeKey = (0, helper_1.escapeSep)(file.path);
|
|
157
|
-
const args = Object.keys(currentModuleScope).filter(arg => !["window", "self", "globalThis", "console"].includes(arg));
|
|
158
|
-
const argValues = args
|
|
159
|
-
.map(arg => `window["${scopeKey}"]["${arg}"]`)
|
|
160
|
-
.join(", ");
|
|
161
|
-
const code = `
|
|
162
|
-
// hijack document.currentScript for auto public path
|
|
163
|
-
var $$g$$ = new Proxy(window, {
|
|
164
|
-
get(target, prop, receiver) {
|
|
165
|
-
if (prop === "document") {
|
|
166
|
-
return new Proxy(window.document, {
|
|
167
|
-
get(target, prop, receiver) {
|
|
168
|
-
if (prop === "currentScript") {
|
|
169
|
-
var script = target.createElement("script");
|
|
170
|
-
script.src = "https://test.cases/path/${(0, helper_1.escapeSep)(file.subPath)}index.js";
|
|
171
|
-
return script;
|
|
172
|
-
}
|
|
173
|
-
return Reflect.get(target, prop, receiver);
|
|
174
|
-
}
|
|
175
|
-
});
|
|
176
|
-
}
|
|
177
|
-
return Reflect.get(target, prop, receiver);
|
|
178
|
-
}
|
|
179
|
-
});
|
|
180
|
-
(function(window, self, globalThis, console, ${args.join(", ")}) {
|
|
181
|
-
${file.content}
|
|
182
|
-
})($$g$$, $$g$$, $$g$$, window["console"], ${argValues});
|
|
183
|
-
`;
|
|
206
|
+
const [m, code] = this.getModuleContent(file);
|
|
184
207
|
this.preExecute(code, file);
|
|
185
|
-
this.dom.window[scopeKey] = currentModuleScope;
|
|
186
208
|
this.dom.window.eval(code);
|
|
187
209
|
this.postExecute(m, file);
|
|
210
|
+
this.requireCache[file.path] = m;
|
|
188
211
|
return m.exports;
|
|
189
212
|
};
|
|
190
213
|
}
|
package/dist/runner/type.d.ts
CHANGED
|
@@ -14,12 +14,12 @@ export declare enum EEsmMode {
|
|
|
14
14
|
Unlinked = 2
|
|
15
15
|
}
|
|
16
16
|
export interface IBasicModuleScope extends ITestEnv {
|
|
17
|
-
console:
|
|
17
|
+
console: Record<string, (...args: any[]) => void>;
|
|
18
18
|
expect: jest.Expect;
|
|
19
19
|
[key: string]: any;
|
|
20
20
|
}
|
|
21
21
|
export interface IBasicGlobalContext {
|
|
22
|
-
console:
|
|
22
|
+
console: Record<string, (...args: any[]) => void>;
|
|
23
23
|
setTimeout: typeof setTimeout;
|
|
24
24
|
clearTimeout: typeof clearTimeout;
|
|
25
25
|
[key: string]: any;
|
package/dist/test/creator.d.ts
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
import type { ECompilerType, ITestContext, ITestEnv, ITestProcessor, ITester, TRunnerFactory, TTestConfig } from "../type";
|
|
2
|
+
declare global {
|
|
3
|
+
var testFilter: string | undefined;
|
|
4
|
+
}
|
|
5
|
+
interface IConcurrentTestEnv {
|
|
6
|
+
clear: () => void;
|
|
7
|
+
run: () => Promise<void>;
|
|
8
|
+
}
|
|
2
9
|
export interface IBasicCaseCreatorOptions<T extends ECompilerType> {
|
|
3
10
|
clean?: boolean;
|
|
4
11
|
describe?: boolean;
|
|
@@ -14,16 +21,26 @@ export interface IBasicCaseCreatorOptions<T extends ECompilerType> {
|
|
|
14
21
|
description?: (name: string, step: number) => string;
|
|
15
22
|
runner?: new (name: string, context: ITestContext) => TRunnerFactory<ECompilerType>;
|
|
16
23
|
[key: string]: unknown;
|
|
24
|
+
concurrent?: boolean | number;
|
|
17
25
|
}
|
|
18
26
|
export declare class BasicCaseCreator<T extends ECompilerType> {
|
|
19
27
|
protected _options: IBasicCaseCreatorOptions<T>;
|
|
28
|
+
protected currentConcurrent: number;
|
|
29
|
+
protected tasks: [string, () => void][];
|
|
20
30
|
constructor(_options: IBasicCaseCreatorOptions<T>);
|
|
21
31
|
create(name: string, src: string, dist: string, temp?: string): ITester | undefined;
|
|
32
|
+
protected shouldRun(name: string): boolean;
|
|
33
|
+
protected describeConcurrent(name: string, tester: ITester, testConfig: TTestConfig<T>): void;
|
|
22
34
|
protected describe(name: string, tester: ITester, testConfig: TTestConfig<T>): void;
|
|
35
|
+
protected createConcurrentEnv(): ITestEnv & IConcurrentTestEnv;
|
|
23
36
|
protected createEnv(testConfig: TTestConfig<T>): ITestEnv;
|
|
24
37
|
protected clean(folders: string[]): void;
|
|
25
38
|
protected skip(name: string, reason: string | boolean): void;
|
|
26
39
|
protected readTestConfig(src: string): TTestConfig<T>;
|
|
27
40
|
protected checkSkipped(src: string, testConfig: TTestConfig<T>): boolean | string;
|
|
28
41
|
protected createTester(name: string, src: string, dist: string, temp: string | void, testConfig: TTestConfig<T>): ITester;
|
|
42
|
+
protected tryRunTask(): void;
|
|
43
|
+
protected getMaxConcurrent(): number;
|
|
44
|
+
protected registerConcurrentTask(name: string, starter: () => void): () => void;
|
|
29
45
|
}
|
|
46
|
+
export {};
|
package/dist/test/creator.js
CHANGED
|
@@ -9,9 +9,12 @@ 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
13
|
class BasicCaseCreator {
|
|
13
14
|
constructor(_options) {
|
|
14
15
|
this._options = _options;
|
|
16
|
+
this.currentConcurrent = 0;
|
|
17
|
+
this.tasks = [];
|
|
15
18
|
}
|
|
16
19
|
create(name, src, dist, temp) {
|
|
17
20
|
const testConfig = this.readTestConfig(src);
|
|
@@ -26,24 +29,113 @@ class BasicCaseCreator {
|
|
|
26
29
|
if (this._options.clean) {
|
|
27
30
|
this.clean([dist, temp || ""].filter(Boolean));
|
|
28
31
|
}
|
|
32
|
+
const run = this.shouldRun(name);
|
|
29
33
|
const tester = this.createTester(name, src, dist, temp, testConfig);
|
|
34
|
+
const concurrent = testConfig.concurrent ?? this._options.concurrent ?? false;
|
|
30
35
|
if (this._options.describe) {
|
|
31
|
-
|
|
36
|
+
if (run) {
|
|
37
|
+
if (concurrent) {
|
|
38
|
+
describe(name, () => this.describeConcurrent(name, tester, testConfig));
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
describe(name, () => this.describe(name, tester, testConfig));
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
describe.skip(name, () => {
|
|
46
|
+
it.skip("skipped", () => { });
|
|
47
|
+
});
|
|
48
|
+
}
|
|
32
49
|
}
|
|
33
50
|
else {
|
|
34
|
-
|
|
51
|
+
if (run) {
|
|
52
|
+
if (concurrent) {
|
|
53
|
+
this.describeConcurrent(name, tester, testConfig);
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
this.describe(name, tester, testConfig);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
it.skip("skipped", () => { });
|
|
61
|
+
}
|
|
35
62
|
}
|
|
36
63
|
return tester;
|
|
37
64
|
}
|
|
65
|
+
shouldRun(name) {
|
|
66
|
+
// TODO: more flexible filter
|
|
67
|
+
if (typeof global.testFilter !== "string" || !global.testFilter) {
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
return name.includes(global.testFilter);
|
|
71
|
+
}
|
|
72
|
+
describeConcurrent(name, tester, testConfig) {
|
|
73
|
+
beforeAll(async () => {
|
|
74
|
+
await tester.prepare();
|
|
75
|
+
});
|
|
76
|
+
let starter = null;
|
|
77
|
+
let chain = new Promise((resolve, reject) => {
|
|
78
|
+
starter = resolve;
|
|
79
|
+
});
|
|
80
|
+
const ender = this.registerConcurrentTask(name, starter);
|
|
81
|
+
const env = this.createConcurrentEnv();
|
|
82
|
+
let bailout = false;
|
|
83
|
+
for (let index = 0; index < tester.total; index++) {
|
|
84
|
+
let stepSignalResolve = null;
|
|
85
|
+
let stepSignalReject = null;
|
|
86
|
+
const stepSignal = new Promise((resolve, reject) => {
|
|
87
|
+
stepSignalResolve = resolve;
|
|
88
|
+
stepSignalReject = reject;
|
|
89
|
+
});
|
|
90
|
+
const description = typeof this._options.description === "function"
|
|
91
|
+
? this._options.description(name, index)
|
|
92
|
+
: index
|
|
93
|
+
? `step [${index}] should pass`
|
|
94
|
+
: "should pass";
|
|
95
|
+
it(description, async () => {
|
|
96
|
+
await stepSignal;
|
|
97
|
+
}, this._options.timeout || 180000);
|
|
98
|
+
chain = chain.then(async () => {
|
|
99
|
+
try {
|
|
100
|
+
if (bailout) {
|
|
101
|
+
throw `Case "${name}" step ${index + 1} bailout because ${tester.step + 1} failed`;
|
|
102
|
+
}
|
|
103
|
+
env.clear();
|
|
104
|
+
await tester.compile();
|
|
105
|
+
await tester.check(env);
|
|
106
|
+
await env.run();
|
|
107
|
+
const context = tester.getContext();
|
|
108
|
+
if (!tester.next() && context.hasError()) {
|
|
109
|
+
bailout = true;
|
|
110
|
+
const errors = context
|
|
111
|
+
.getError()
|
|
112
|
+
.map(i => `${i.stack}`.split("\n").join("\t\n"))
|
|
113
|
+
.join("\n\n");
|
|
114
|
+
throw new Error(`Case "${name}" failed at step ${tester.step + 1}:\n${errors}`);
|
|
115
|
+
}
|
|
116
|
+
stepSignalResolve();
|
|
117
|
+
}
|
|
118
|
+
catch (e) {
|
|
119
|
+
stepSignalReject(e);
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
chain.finally(() => {
|
|
124
|
+
ender();
|
|
125
|
+
});
|
|
126
|
+
afterAll(async () => {
|
|
127
|
+
await tester.resume();
|
|
128
|
+
});
|
|
129
|
+
}
|
|
38
130
|
describe(name, tester, testConfig) {
|
|
39
131
|
beforeAll(async () => {
|
|
40
132
|
await tester.prepare();
|
|
41
133
|
});
|
|
134
|
+
let bailout = false;
|
|
42
135
|
for (let index = 0; index < tester.total; index++) {
|
|
43
136
|
const description = typeof this._options.description === "function"
|
|
44
137
|
? this._options.description(name, index)
|
|
45
138
|
: `step ${index ? `[${index}]` : ""} should pass`;
|
|
46
|
-
let bailout = false;
|
|
47
139
|
it(description, async () => {
|
|
48
140
|
if (bailout) {
|
|
49
141
|
throw `Case "${name}" step ${index + 1} bailout because ${tester.step + 1} failed`;
|
|
@@ -66,6 +158,69 @@ class BasicCaseCreator {
|
|
|
66
158
|
await tester.resume();
|
|
67
159
|
});
|
|
68
160
|
}
|
|
161
|
+
createConcurrentEnv() {
|
|
162
|
+
const tasks = [];
|
|
163
|
+
const beforeTasks = [];
|
|
164
|
+
const afterTasks = [];
|
|
165
|
+
return {
|
|
166
|
+
clear: () => {
|
|
167
|
+
tasks.length = 0;
|
|
168
|
+
beforeTasks.length = 0;
|
|
169
|
+
afterTasks.length = 0;
|
|
170
|
+
},
|
|
171
|
+
run: async () => {
|
|
172
|
+
const runFn = async (fn) => {
|
|
173
|
+
if (fn.length) {
|
|
174
|
+
await new Promise((resolve, reject) => {
|
|
175
|
+
fn(e => {
|
|
176
|
+
if (e) {
|
|
177
|
+
reject(e);
|
|
178
|
+
}
|
|
179
|
+
else {
|
|
180
|
+
resolve();
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
const res = fn();
|
|
187
|
+
if (typeof res?.then === "function") {
|
|
188
|
+
await res;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
for (const [description, fn] of tasks) {
|
|
193
|
+
for (const before of beforeTasks) {
|
|
194
|
+
await runFn(before);
|
|
195
|
+
}
|
|
196
|
+
try {
|
|
197
|
+
await runFn(fn);
|
|
198
|
+
}
|
|
199
|
+
catch (e) {
|
|
200
|
+
throw new Error(`Error: ${description} failed\n${e.stack}`);
|
|
201
|
+
}
|
|
202
|
+
for (const after of afterTasks) {
|
|
203
|
+
await runFn(after);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
},
|
|
207
|
+
expect,
|
|
208
|
+
it: (description, fn) => {
|
|
209
|
+
expect(typeof description === "string");
|
|
210
|
+
expect(typeof fn === "function");
|
|
211
|
+
tasks.push([description, fn]);
|
|
212
|
+
},
|
|
213
|
+
beforeEach: (fn) => {
|
|
214
|
+
expect(typeof fn === "function");
|
|
215
|
+
beforeTasks.push(fn);
|
|
216
|
+
},
|
|
217
|
+
afterEach: (fn) => {
|
|
218
|
+
expect(typeof fn === "function");
|
|
219
|
+
afterTasks.push(fn);
|
|
220
|
+
},
|
|
221
|
+
jest
|
|
222
|
+
};
|
|
223
|
+
}
|
|
69
224
|
createEnv(testConfig) {
|
|
70
225
|
if (typeof this._options.runner === "function" && !testConfig.noTest) {
|
|
71
226
|
return (0, createLazyTestEnv_1.default)(10000);
|
|
@@ -115,5 +270,26 @@ class BasicCaseCreator {
|
|
|
115
270
|
})
|
|
116
271
|
});
|
|
117
272
|
}
|
|
273
|
+
tryRunTask() {
|
|
274
|
+
while (this.tasks.length !== 0 &&
|
|
275
|
+
this.currentConcurrent < this.getMaxConcurrent()) {
|
|
276
|
+
const [_name, starter] = this.tasks.shift();
|
|
277
|
+
this.currentConcurrent++;
|
|
278
|
+
starter();
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
getMaxConcurrent() {
|
|
282
|
+
return typeof this._options.concurrent === "number"
|
|
283
|
+
? this._options.concurrent
|
|
284
|
+
: DEFAULT_MAX_CONCURRENT;
|
|
285
|
+
}
|
|
286
|
+
registerConcurrentTask(name, starter) {
|
|
287
|
+
this.tasks.push([name, starter]);
|
|
288
|
+
this.tryRunTask();
|
|
289
|
+
return () => {
|
|
290
|
+
this.currentConcurrent--;
|
|
291
|
+
this.tryRunTask();
|
|
292
|
+
};
|
|
293
|
+
}
|
|
118
294
|
}
|
|
119
295
|
exports.BasicCaseCreator = BasicCaseCreator;
|
package/dist/type.d.ts
CHANGED
|
@@ -141,12 +141,13 @@ export type TTestConfig<T extends ECompilerType> = {
|
|
|
141
141
|
beforeExecute?: () => void;
|
|
142
142
|
afterExecute?: () => void;
|
|
143
143
|
moduleScope?: (ms: IBasicModuleScope, stats?: TCompilerStatsCompilation<T>) => IBasicModuleScope;
|
|
144
|
-
checkStats?: (stepName: string, jsonStats: TCompilerStatsCompilation<T
|
|
144
|
+
checkStats?: (stepName: string, jsonStats: TCompilerStatsCompilation<T> | undefined, stringStats: String) => boolean;
|
|
145
145
|
findBundle?: (index: number, options: TCompilerOptions<T>, stepName?: string) => string | string[];
|
|
146
146
|
bundlePath?: string[];
|
|
147
147
|
nonEsmThis?: (p: string | string[]) => Object;
|
|
148
148
|
modules?: Record<string, Object>;
|
|
149
149
|
timeout?: number;
|
|
150
|
+
concurrent?: boolean;
|
|
150
151
|
};
|
|
151
152
|
export type TTestFilter<T extends ECompilerType> = (creatorConfig: Record<string, unknown>, testConfig: TTestConfig<T>) => boolean | string;
|
|
152
153
|
export interface ITestRunner {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rspack/test-tools",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.8",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Test tools for rspack",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"@babel/generator": "7.26.9",
|
|
35
35
|
"@babel/helpers": "7.26.9",
|
|
36
36
|
"@babel/parser": "7.26.9",
|
|
37
|
-
"@babel/template": "7.
|
|
37
|
+
"@babel/template": "7.26.9",
|
|
38
38
|
"@babel/traverse": "7.26.9",
|
|
39
39
|
"@babel/types": "7.26.9",
|
|
40
40
|
"cross-env": "^7.0.3",
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"pretty-format": "29.7.0",
|
|
54
54
|
"rimraf": "^5.0.10",
|
|
55
55
|
"source-map": "^0.7.4",
|
|
56
|
-
"terser-webpack-plugin": "^5.3.
|
|
56
|
+
"terser-webpack-plugin": "^5.3.13",
|
|
57
57
|
"webpack": "5.98.0",
|
|
58
58
|
"webpack-merge": "5.9.0",
|
|
59
59
|
"webpack-sources": "3.2.3"
|
|
@@ -74,17 +74,17 @@
|
|
|
74
74
|
"@types/webpack": "5.28.5",
|
|
75
75
|
"@types/webpack-sources": "3.2.3",
|
|
76
76
|
"@webdiscus/pug-loader": "^2.11.1",
|
|
77
|
-
"acorn": "^8.14.
|
|
78
|
-
"babel-loader": "^
|
|
77
|
+
"acorn": "^8.14.1",
|
|
78
|
+
"babel-loader": "^10.0.0",
|
|
79
79
|
"babel-plugin-import": "^1.13.8",
|
|
80
80
|
"chalk": "^4.1.2",
|
|
81
81
|
"coffee-loader": "^5.0.0",
|
|
82
82
|
"coffeescript": "^2.7.0",
|
|
83
|
-
"core-js": "3.
|
|
83
|
+
"core-js": "3.41.0",
|
|
84
84
|
"css-loader": "^7.1.2",
|
|
85
85
|
"file-loader": "^6.2.0",
|
|
86
86
|
"graceful-fs": "^4.2.11",
|
|
87
|
-
"html-loader": "^5.
|
|
87
|
+
"html-loader": "^5.1.0",
|
|
88
88
|
"html-webpack-plugin": "^5.6.3",
|
|
89
89
|
"less-loader": "^12.2.0",
|
|
90
90
|
"lodash": "^4.17.21",
|
|
@@ -106,9 +106,9 @@
|
|
|
106
106
|
"typescript": "^5.7.3",
|
|
107
107
|
"wast-loader": "^1.14.1",
|
|
108
108
|
"worker-rspack-loader": "^3.1.2",
|
|
109
|
-
"@rspack/cli": "1.2.
|
|
110
|
-
"@rspack/core": "1.2.
|
|
111
|
-
"@rspack/test-tools": "1.2.
|
|
109
|
+
"@rspack/cli": "1.2.8",
|
|
110
|
+
"@rspack/core": "1.2.8",
|
|
111
|
+
"@rspack/test-tools": "1.2.8"
|
|
112
112
|
},
|
|
113
113
|
"peerDependencies": {
|
|
114
114
|
"@rspack/core": ">=1.0.0"
|
|
@@ -120,9 +120,9 @@
|
|
|
120
120
|
"dev": "tsc -b -w",
|
|
121
121
|
"test": "pnpm run --stream /^test:.*/",
|
|
122
122
|
"testu": "pnpm run --stream /^test:.*/ -u",
|
|
123
|
-
"test:base": "cross-env
|
|
124
|
-
"test:hot": "cross-env RSPACK_HOT_TEST=true
|
|
125
|
-
"test:diff": "cross-env RSPACK_DIFF=true
|
|
123
|
+
"test:base": "cross-env node --no-warnings --expose-gc --max-old-space-size=8192 --experimental-vm-modules ../../node_modules/jest-cli/bin/jest --logHeapUsage --colors --config ./jest.config.js --passWithNoTests",
|
|
124
|
+
"test:hot": "cross-env RSPACK_HOT_TEST=true node --no-warnings --expose-gc --max-old-space-size=8192 --experimental-vm-modules ../../node_modules/jest-cli/bin/jest --logHeapUsage --colors --config ./jest.config.hot.js --passWithNoTests",
|
|
125
|
+
"test:diff": "cross-env RSPACK_DIFF=true node --no-warnings --expose-gc --max-old-space-size=8192 --experimental-vm-modules ../../node_modules/jest-cli/bin/jest --logHeapUsage --colors --config ./jest.config.diff.js --passWithNoTests",
|
|
126
126
|
"api-extractor": "api-extractor run --verbose",
|
|
127
127
|
"api-extractor:ci": "api-extractor run --verbose || diff temp/test-tools.api.md etc/test-tools.api.md"
|
|
128
128
|
}
|