2018-05-15 19:19:53 +08:00
|
|
|
"use strict";
|
|
|
|
|
2021-09-09 00:35:00 +08:00
|
|
|
require("./helpers/warmup-webpack");
|
|
|
|
|
2018-05-15 19:19:53 +08:00
|
|
|
const path = require("path");
|
2025-07-03 17:06:45 +08:00
|
|
|
const _ = require("lodash");
|
|
|
|
const { Volume, createFsFromVolume } = require("memfs");
|
2021-04-06 21:20:27 +08:00
|
|
|
const webpack = require("..");
|
2019-06-05 00:33:55 +08:00
|
|
|
const captureStdio = require("./helpers/captureStdio");
|
2018-05-15 19:19:53 +08:00
|
|
|
|
2021-02-14 04:13:48 +08:00
|
|
|
const createMultiCompiler = (progressOptions, configOptions) => {
|
|
|
|
const compiler = webpack(
|
|
|
|
Object.assign(
|
|
|
|
[
|
|
|
|
{
|
|
|
|
context: path.join(__dirname, "fixtures"),
|
|
|
|
entry: "./a.js"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
context: path.join(__dirname, "fixtures"),
|
|
|
|
entry: "./b.js"
|
|
|
|
}
|
|
|
|
],
|
|
|
|
configOptions
|
|
|
|
)
|
|
|
|
);
|
|
|
|
compiler.outputFileSystem = createFsFromVolume(new Volume());
|
|
|
|
|
|
|
|
new webpack.ProgressPlugin(progressOptions).apply(compiler);
|
|
|
|
|
|
|
|
return compiler;
|
|
|
|
};
|
|
|
|
|
2025-07-17 00:13:14 +08:00
|
|
|
const createSimpleCompiler = (progressOptions) => {
|
2021-02-14 04:13:48 +08:00
|
|
|
const compiler = webpack({
|
|
|
|
context: path.join(__dirname, "fixtures"),
|
|
|
|
entry: "./a.js",
|
|
|
|
infrastructureLogging: {
|
|
|
|
debug: /Progress/
|
2022-02-23 21:01:47 +08:00
|
|
|
},
|
|
|
|
plugins: [
|
|
|
|
new webpack.ProgressPlugin({
|
|
|
|
activeModules: true,
|
|
|
|
...progressOptions
|
|
|
|
})
|
|
|
|
]
|
2021-02-14 04:13:48 +08:00
|
|
|
});
|
|
|
|
|
|
|
|
compiler.outputFileSystem = createFsFromVolume(new Volume());
|
|
|
|
|
|
|
|
return compiler;
|
|
|
|
};
|
|
|
|
|
2025-07-17 00:13:14 +08:00
|
|
|
const createSimpleCompilerWithCustomHandler = (options) => {
|
2021-02-14 04:13:48 +08:00
|
|
|
const compiler = webpack({
|
|
|
|
context: path.join(__dirname, "fixtures"),
|
|
|
|
entry: "./a.js"
|
|
|
|
});
|
|
|
|
|
|
|
|
compiler.outputFileSystem = createFsFromVolume(new Volume());
|
|
|
|
const logger = compiler.getInfrastructureLogger("custom test logger");
|
|
|
|
new webpack.ProgressPlugin({
|
|
|
|
activeModules: true,
|
|
|
|
...options,
|
|
|
|
handler: (...args) => logger.status(args)
|
|
|
|
}).apply(compiler);
|
|
|
|
|
|
|
|
return compiler;
|
|
|
|
};
|
|
|
|
|
2025-07-17 00:13:14 +08:00
|
|
|
const getLogs = (logsStr) => logsStr.split(/\r/).filter((v) => v !== " ");
|
2021-02-14 04:13:48 +08:00
|
|
|
|
2025-07-17 00:13:14 +08:00
|
|
|
const runCompilerAsync = (compiler) =>
|
2021-02-14 04:13:48 +08:00
|
|
|
new Promise((resolve, reject) => {
|
2025-07-17 00:13:14 +08:00
|
|
|
compiler.run((err) => {
|
2021-02-14 04:13:48 +08:00
|
|
|
if (err) {
|
|
|
|
reject(err);
|
|
|
|
} else {
|
|
|
|
resolve();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2025-07-02 20:10:54 +08:00
|
|
|
describe("ProgressPlugin", () => {
|
2019-06-04 06:27:38 +08:00
|
|
|
let stderr;
|
2020-04-16 15:37:11 +08:00
|
|
|
let stdout;
|
2019-06-04 06:27:38 +08:00
|
|
|
|
|
|
|
beforeEach(() => {
|
2019-08-01 14:18:45 +08:00
|
|
|
stderr = captureStdio(process.stderr, true);
|
2020-04-16 15:37:11 +08:00
|
|
|
stdout = captureStdio(process.stdout, true);
|
2019-06-04 06:27:38 +08:00
|
|
|
});
|
2025-07-02 20:10:54 +08:00
|
|
|
|
2019-06-04 06:27:38 +08:00
|
|
|
afterEach(() => {
|
2025-07-02 20:10:54 +08:00
|
|
|
// eslint-disable-next-line no-unused-expressions
|
2019-06-04 06:27:38 +08:00
|
|
|
stderr && stderr.restore();
|
2025-07-02 20:10:54 +08:00
|
|
|
// eslint-disable-next-line no-unused-expressions
|
2020-04-16 15:37:11 +08:00
|
|
|
stdout && stdout.restore();
|
2019-06-04 06:27:38 +08:00
|
|
|
});
|
|
|
|
|
2025-07-17 00:13:14 +08:00
|
|
|
const nanTest = (createCompiler) => () => {
|
2021-02-14 04:13:48 +08:00
|
|
|
const compiler = createCompiler();
|
2018-05-15 19:19:53 +08:00
|
|
|
|
2024-07-31 11:50:02 +08:00
|
|
|
return runCompilerAsync(compiler).then(() => {
|
2019-06-05 00:33:55 +08:00
|
|
|
expect(stderr.toString()).toContain("%");
|
2019-06-04 06:27:38 +08:00
|
|
|
expect(stderr.toString()).not.toContain("NaN");
|
2018-05-15 19:19:53 +08:00
|
|
|
});
|
2021-02-14 04:13:48 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
it(
|
|
|
|
"should not contain NaN as a percentage when it is applied to Compiler",
|
|
|
|
nanTest(createSimpleCompiler)
|
|
|
|
);
|
2025-07-02 20:10:54 +08:00
|
|
|
|
2021-02-14 04:13:48 +08:00
|
|
|
it(
|
|
|
|
"should not contain NaN as a percentage when it is applied to MultiCompiler",
|
|
|
|
nanTest(createMultiCompiler)
|
|
|
|
);
|
2025-07-02 20:10:54 +08:00
|
|
|
|
2021-02-14 04:13:48 +08:00
|
|
|
it(
|
2021-12-13 05:57:14 +08:00
|
|
|
"should not contain NaN as a percentage when it is applied to MultiCompiler (parallelism: 1)",
|
2021-02-14 04:13:48 +08:00
|
|
|
nanTest(() => createMultiCompiler(undefined, { parallelism: 1 }))
|
|
|
|
);
|
2019-06-04 06:27:38 +08:00
|
|
|
|
2025-07-17 00:13:14 +08:00
|
|
|
it("should start print only on call run/watch", (done) => {
|
2022-02-23 21:01:47 +08:00
|
|
|
const compiler = createSimpleCompiler();
|
|
|
|
|
|
|
|
const logs = getLogs(stderr.toString());
|
|
|
|
expect(logs.join("")).toHaveLength(0);
|
|
|
|
|
|
|
|
compiler.close(done);
|
|
|
|
});
|
|
|
|
|
2020-04-16 15:37:11 +08:00
|
|
|
it("should print profile information", () => {
|
|
|
|
const compiler = createSimpleCompiler({
|
|
|
|
profile: true
|
|
|
|
});
|
|
|
|
|
2024-07-31 11:50:02 +08:00
|
|
|
return runCompilerAsync(compiler).then(() => {
|
2020-04-16 15:37:11 +08:00
|
|
|
const logs = getLogs(stderr.toString());
|
|
|
|
|
|
|
|
expect(logs).toContainEqual(
|
|
|
|
expect.stringMatching(
|
2020-07-31 23:38:33 +08:00
|
|
|
/\[webpack\.Progress\] {2}| {2}| \d+ ms module ids > DeterministicModuleIdsPlugin\n$/
|
2020-04-16 15:37:11 +08:00
|
|
|
)
|
|
|
|
);
|
|
|
|
expect(logs).toContainEqual(
|
|
|
|
expect.stringMatching(
|
2020-07-31 23:38:33 +08:00
|
|
|
/\[webpack\.Progress\] {2}| \d+ ms building > \.\.\. entries \.\.\. dependencies \.\.\. modules\n$/
|
2020-04-16 15:37:11 +08:00
|
|
|
)
|
|
|
|
);
|
2020-07-31 23:38:33 +08:00
|
|
|
expect(logs).toContainEqual(
|
|
|
|
expect.stringMatching(/\[webpack\.Progress\] \d+ ms building\n$/)
|
|
|
|
);
|
|
|
|
expect(logs).toContainEqual(
|
|
|
|
expect.stringMatching(
|
|
|
|
/\[webpack\.Progress\] {2}| \d+ ms sealing > module ids\n$/
|
|
|
|
)
|
|
|
|
);
|
|
|
|
expect(logs).toContainEqual(
|
|
|
|
expect.stringMatching(/\[webpack\.Progress\] \d+ ms sealing\n$/)
|
|
|
|
);
|
2020-04-16 15:37:11 +08:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2025-07-17 00:13:14 +08:00
|
|
|
const monotonicTest = (createCompiler) => () => {
|
2020-04-29 02:57:33 +08:00
|
|
|
const handlerCalls = [];
|
2021-02-14 04:13:48 +08:00
|
|
|
const compiler = createCompiler({
|
2020-04-29 02:57:33 +08:00
|
|
|
handler: (p, ...args) => {
|
|
|
|
handlerCalls.push({ value: p, text: `${p}% ${args.join(" ")}` });
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2024-07-31 11:50:02 +08:00
|
|
|
return runCompilerAsync(compiler).then(() => {
|
2020-04-29 02:57:33 +08:00
|
|
|
let lastLine = handlerCalls[0];
|
|
|
|
for (const line of handlerCalls) {
|
|
|
|
if (line.value < lastLine.value) {
|
|
|
|
throw new Error(
|
|
|
|
`Progress value is not monotonic increasing:\n${lastLine.text}\n${line.text}`
|
|
|
|
);
|
|
|
|
}
|
|
|
|
lastLine = line;
|
|
|
|
}
|
|
|
|
});
|
2021-02-14 04:13:48 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
it(
|
|
|
|
"should have monotonic increasing progress",
|
|
|
|
monotonicTest(createSimpleCompiler)
|
|
|
|
);
|
2025-07-02 20:10:54 +08:00
|
|
|
|
2021-02-14 04:13:48 +08:00
|
|
|
it(
|
|
|
|
"should have monotonic increasing progress (multi compiler)",
|
|
|
|
monotonicTest(createMultiCompiler)
|
|
|
|
);
|
2025-07-02 20:10:54 +08:00
|
|
|
|
2021-02-14 04:13:48 +08:00
|
|
|
it(
|
|
|
|
"should have monotonic increasing progress (multi compiler, parallelism)",
|
2025-07-17 00:13:14 +08:00
|
|
|
monotonicTest((o) => createMultiCompiler(o, { parallelism: 1 }))
|
2021-02-14 04:13:48 +08:00
|
|
|
);
|
2020-04-29 02:57:33 +08:00
|
|
|
|
2019-06-05 00:33:55 +08:00
|
|
|
it("should not print lines longer than stderr.columns", () => {
|
|
|
|
const compiler = createSimpleCompiler();
|
2019-08-05 19:32:25 +08:00
|
|
|
process.stderr.columns = 36;
|
2019-06-05 00:33:55 +08:00
|
|
|
|
2024-07-31 11:50:02 +08:00
|
|
|
return runCompilerAsync(compiler).then(() => {
|
2019-06-05 00:33:55 +08:00
|
|
|
const logs = getLogs(stderr.toString());
|
|
|
|
|
|
|
|
expect(logs.length).toBeGreaterThan(20);
|
2024-08-02 02:36:27 +08:00
|
|
|
for (const log of logs) {
|
|
|
|
expect(log.length).toBeLessThanOrEqual(35);
|
|
|
|
}
|
2022-01-18 17:38:06 +08:00
|
|
|
// cspell:ignore mization nsPlugin
|
2019-06-05 00:33:55 +08:00
|
|
|
expect(logs).toContain(
|
2020-07-31 23:38:33 +08:00
|
|
|
"75% sealing ...mization ...nsPlugin",
|
2019-06-05 00:33:55 +08:00
|
|
|
"trims each detail string equally"
|
|
|
|
);
|
2020-07-31 23:38:33 +08:00
|
|
|
expect(logs).toContain("92% sealing asset processing");
|
2019-08-05 18:15:03 +08:00
|
|
|
expect(logs).toContain("100%");
|
2019-06-05 00:33:55 +08:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should handle when stderr.columns is undefined", () => {
|
|
|
|
const compiler = createSimpleCompiler();
|
|
|
|
|
|
|
|
process.stderr.columns = undefined;
|
2024-07-31 11:50:02 +08:00
|
|
|
return runCompilerAsync(compiler).then(() => {
|
2019-06-05 00:33:55 +08:00
|
|
|
const logs = getLogs(stderr.toString());
|
|
|
|
|
|
|
|
expect(logs.length).toBeGreaterThan(20);
|
2023-03-12 09:57:19 +08:00
|
|
|
expect(_.maxBy(logs, "length").length).not.toBeGreaterThan(40);
|
2019-06-05 00:33:55 +08:00
|
|
|
});
|
|
|
|
});
|
2020-01-30 17:20:48 +08:00
|
|
|
|
2020-04-19 01:03:02 +08:00
|
|
|
it("should contain the new compiler hooks", () => {
|
|
|
|
const compiler = createSimpleCompiler();
|
|
|
|
|
|
|
|
process.stderr.columns = undefined;
|
2024-07-31 11:50:02 +08:00
|
|
|
return runCompilerAsync(compiler).then(() => {
|
2020-04-19 01:03:02 +08:00
|
|
|
const logs = getLogs(stderr.toString());
|
|
|
|
|
2020-07-31 23:38:33 +08:00
|
|
|
expect(logs).toContain("4% setup normal module factory");
|
|
|
|
expect(logs).toContain("5% setup context module factory");
|
2020-04-19 01:03:02 +08:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2020-01-30 17:20:48 +08:00
|
|
|
it("should display all type of percentage when it is applied to SingleCompiler", () => {
|
|
|
|
const compiler = createSimpleCompiler({
|
|
|
|
entries: true,
|
|
|
|
modules: true,
|
|
|
|
dependencies: true,
|
|
|
|
activeModules: true
|
|
|
|
});
|
|
|
|
|
2023-03-12 18:25:43 +08:00
|
|
|
process.stderr.columns = 70;
|
2024-07-31 11:50:02 +08:00
|
|
|
return runCompilerAsync(compiler).then(() => {
|
2020-01-30 17:20:48 +08:00
|
|
|
const logs = stderr.toString();
|
|
|
|
|
|
|
|
expect(logs).toEqual(expect.stringMatching(/\d+\/\d+ entries/));
|
|
|
|
expect(logs).toEqual(expect.stringMatching(/\d+\/\d+ dependencies/));
|
|
|
|
expect(logs).toEqual(expect.stringMatching(/\d+\/\d+ modules/));
|
|
|
|
expect(logs).toEqual(expect.stringMatching(/\d+ active/));
|
|
|
|
});
|
|
|
|
});
|
2020-04-05 16:24:59 +08:00
|
|
|
|
|
|
|
it("should get the custom handler text from the log", () => {
|
|
|
|
const compiler = createSimpleCompilerWithCustomHandler();
|
|
|
|
|
2023-03-12 18:25:43 +08:00
|
|
|
process.stderr.columns = 70;
|
2024-07-31 11:50:02 +08:00
|
|
|
return runCompilerAsync(compiler).then(() => {
|
2020-04-05 16:24:59 +08:00
|
|
|
const logs = stderr.toString();
|
|
|
|
expect(logs).toEqual(
|
|
|
|
expect.stringMatching(/\d+\/\d+ [custom test logger]/)
|
|
|
|
);
|
|
|
|
expect(logs).toEqual(expect.stringMatching(/\d+ active/));
|
|
|
|
expect(logs).toEqual(expect.stringMatching(/\d+\/\d+ modules/));
|
|
|
|
});
|
|
|
|
});
|
2019-06-05 00:33:55 +08:00
|
|
|
});
|