Sitelet https://github.com/webpack/webpack/commit/955a68cd81474b6348d2b341e1ae9968fa50a3b9
Skip to content

Commit 955a68c

Browse files
authored
test: generate snapshots per stats test case (#20785)
1 parent 47bb540 commit 955a68c

131 files changed

Lines changed: 5336 additions & 5191 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎test/StatsTestCases.basictest.js‎

Lines changed: 185 additions & 168 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ const path = require("path");
66
const fs = require("graceful-fs");
77
const rimraf = require("rimraf");
88
const webpack = require("..");
9+
const { registerPerCaseSnapshotHooks } = require("./harness/snapshot");
910
const captureStdio = require("./helpers/captureStdio");
1011

1112
/**
@@ -49,191 +50,207 @@ describe("StatsTestCases", () => {
4950
});
5051

5152
for (const testName of tests) {
53+
const testDirectory = path.join(base, testName);
54+
5255
// eslint-disable-next-line no-loop-func
53-
it(`should print correct stats for ${testName}`, (done) => {
54-
const outputDirectory = path.join(outputBase, testName);
55-
rimraf.sync(outputDirectory);
56-
fs.mkdirSync(outputDirectory, { recursive: true });
57-
let options = {
58-
mode: "development",
59-
entry: "./index",
60-
output: {
61-
filename: "bundle.js"
62-
}
63-
};
64-
if (fs.existsSync(path.join(base, testName, "webpack.config.js"))) {
65-
options = require(path.join(base, testName, "webpack.config.js"));
66-
}
67-
let testConfig = {};
68-
try {
69-
// try to load a test file
70-
testConfig = Object.assign(
71-
testConfig,
72-
require(path.join(base, testName, "test.config.js"))
73-
);
74-
} catch (_err) {
75-
// ignored
76-
}
56+
describe(testName, () => {
57+
registerPerCaseSnapshotHooks(testDirectory, "StatsTestCases");
7758

78-
const resolvedOptions = Array.isArray(options) ? options : [options];
79-
for (const options of resolvedOptions) {
80-
if (!options.context) options.context = path.join(base, testName);
81-
if (!options.output) options.output = options.output || {};
82-
if (!options.output.path) options.output.path = outputDirectory;
83-
if (!options.plugins) options.plugins = [];
84-
if (!options.optimization) options.optimization = {};
85-
if (options.optimization.minimize === undefined) {
86-
options.optimization.minimize = false;
59+
it(`should print correct stats for ${testName}`, (done) => {
60+
const outputDirectory = path.join(outputBase, testName);
61+
rimraf.sync(outputDirectory);
62+
fs.mkdirSync(outputDirectory, { recursive: true });
63+
let options = {
64+
mode: "development",
65+
entry: "./index",
66+
output: {
67+
filename: "bundle.js"
68+
}
69+
};
70+
if (fs.existsSync(path.join(testDirectory, "webpack.config.js"))) {
71+
options = require(path.join(testDirectory, "webpack.config.js"));
8772
}
88-
if (
89-
options.cache &&
90-
options.cache !== true &&
91-
options.cache.type === "filesystem"
92-
) {
93-
options.cache.cacheDirectory = path.resolve(
94-
outputBase,
95-
".cache",
96-
testName
73+
let testConfig = {};
74+
try {
75+
// try to load a test file
76+
testConfig = Object.assign(
77+
testConfig,
78+
require(path.join(testDirectory, "test.config.js"))
9779
);
80+
} catch (_err) {
81+
// ignored
82+
}
83+
84+
const resolvedOptions = Array.isArray(options) ? options : [options];
85+
for (const options of resolvedOptions) {
86+
if (!options.context) options.context = testDirectory;
87+
if (!options.output) options.output = options.output || {};
88+
if (!options.output.path) options.output.path = outputDirectory;
89+
if (!options.plugins) options.plugins = [];
90+
if (!options.optimization) options.optimization = {};
91+
if (options.optimization.minimize === undefined) {
92+
options.optimization.minimize = false;
93+
}
94+
if (
95+
options.cache &&
96+
options.cache !== true &&
97+
options.cache.type === "filesystem"
98+
) {
99+
options.cache.cacheDirectory = path.resolve(
100+
outputBase,
101+
".cache",
102+
testName
103+
);
104+
}
98105
}
99-
}
100-
const c = webpack(options);
101-
const compilers = c.compilers ? c.compilers : [c];
102-
for (const c of compilers) {
103-
const ifs = c.inputFileSystem;
104-
c.inputFileSystem = Object.create(ifs);
105-
c.inputFileSystem.readFile = function readFile() {
106-
// eslint-disable-next-line prefer-rest-params
107-
const args = Array.prototype.slice.call(arguments);
108-
const callback = args.pop();
109-
// eslint-disable-next-line no-useless-call
110-
ifs.readFile.apply(ifs, [
111-
...args,
112-
(err, result) => {
113-
if (err) return callback(err);
114-
if (!/\.(?:js|json|txt)$/.test(args[0])) {
115-
return callback(null, result);
106+
const c = webpack(options);
107+
const compilers = c.compilers ? c.compilers : [c];
108+
for (const c of compilers) {
109+
const ifs = c.inputFileSystem;
110+
c.inputFileSystem = Object.create(ifs);
111+
c.inputFileSystem.readFile = function readFile() {
112+
// eslint-disable-next-line prefer-rest-params
113+
const args = Array.prototype.slice.call(arguments);
114+
const callback = args.pop();
115+
// eslint-disable-next-line no-useless-call
116+
ifs.readFile.apply(ifs, [
117+
...args,
118+
(err, result) => {
119+
if (err) return callback(err);
120+
if (!/\.(?:js|json|txt)$/.test(args[0])) {
121+
return callback(null, result);
122+
}
123+
callback(null, result.toString("utf8").replace(/\r/g, ""));
116124
}
117-
callback(null, result.toString("utf8").replace(/\r/g, ""));
125+
]);
126+
};
127+
c.hooks.compilation.tap("StatsTestCasesTest", (compilation) => {
128+
for (const hook of [
129+
"optimize",
130+
"optimizeModules",
131+
"optimizeChunks",
132+
"afterOptimizeTree",
133+
"afterOptimizeAssets",
134+
"beforeHash"
135+
]) {
136+
compilation.hooks[hook].tap("TestCasesTest", () =>
137+
compilation.checkConstraints()
138+
);
118139
}
119-
]);
120-
};
121-
c.hooks.compilation.tap("StatsTestCasesTest", (compilation) => {
122-
for (const hook of [
123-
"optimize",
124-
"optimizeModules",
125-
"optimizeChunks",
126-
"afterOptimizeTree",
127-
"afterOptimizeAssets",
128-
"beforeHash"
129-
]) {
130-
compilation.hooks[hook].tap("TestCasesTest", () =>
131-
compilation.checkConstraints()
140+
});
141+
}
142+
c.run((err, stats) => {
143+
if (err) return done(err);
144+
for (const compilation of [
145+
...(stats.stats ? stats.stats : [stats])
146+
].map((s) => s.compilation)) {
147+
compilation.logging.delete("webpack.Compilation.ModuleProfile");
148+
}
149+
expect(stats.hasErrors()).toBe(testName.endsWith("error"));
150+
if (!testName.endsWith("error") && stats.hasErrors()) {
151+
return done(
152+
new Error(
153+
stats.toString({
154+
all: false,
155+
errors: true,
156+
errorStack: true,
157+
errorDetails: true
158+
})
159+
)
132160
);
133161
}
134-
});
135-
}
136-
c.run((err, stats) => {
137-
if (err) return done(err);
138-
for (const compilation of [
139-
...(stats.stats ? stats.stats : [stats])
140-
].map((s) => s.compilation)) {
141-
compilation.logging.delete("webpack.Compilation.ModuleProfile");
142-
}
143-
expect(stats.hasErrors()).toBe(testName.endsWith("error"));
144-
if (!testName.endsWith("error") && stats.hasErrors()) {
145-
return done(
146-
new Error(
147-
stats.toString({
148-
all: false,
149-
errors: true,
150-
errorStack: true,
151-
errorDetails: true
152-
})
153-
)
162+
fs.writeFileSync(
163+
path.join(outputBase, testName, "stats.txt"),
164+
stats.toString({
165+
preset: "verbose",
166+
context: testDirectory,
167+
colors: false
168+
}),
169+
"utf8"
154170
);
155-
}
156-
fs.writeFileSync(
157-
path.join(outputBase, testName, "stats.txt"),
158-
stats.toString({
159-
preset: "verbose",
160-
context: path.join(base, testName),
161-
colors: false
162-
}),
163-
"utf8"
164-
);
165171

166-
let toStringOptions = {
167-
context: path.join(base, testName),
168-
colors: false
169-
};
170-
let hasColorSetting = false;
171-
if (typeof c.options.stats !== "undefined") {
172-
toStringOptions = c.options.stats;
173-
if (toStringOptions === null || typeof toStringOptions !== "object") {
174-
toStringOptions = { preset: toStringOptions };
172+
let toStringOptions = {
173+
context: testDirectory,
174+
colors: false
175+
};
176+
let hasColorSetting = false;
177+
if (typeof c.options.stats !== "undefined") {
178+
toStringOptions = c.options.stats;
179+
if (
180+
toStringOptions === null ||
181+
typeof toStringOptions !== "object"
182+
) {
183+
toStringOptions = { preset: toStringOptions };
184+
}
185+
if (!toStringOptions.context) {
186+
toStringOptions.context = testDirectory;
187+
}
188+
hasColorSetting = typeof toStringOptions.colors !== "undefined";
175189
}
176-
if (!toStringOptions.context) {
177-
toStringOptions.context = path.join(base, testName);
190+
if (Array.isArray(c.options) && !toStringOptions.children) {
191+
toStringOptions.children = c.options.map((o) => o.stats);
178192
}
179-
hasColorSetting = typeof toStringOptions.colors !== "undefined";
180-
}
181-
if (Array.isArray(c.options) && !toStringOptions.children) {
182-
toStringOptions.children = c.options.map((o) => o.stats);
183-
}
184-
// mock timestamps
185-
for (const { compilation: s } of stats.stats ? stats.stats : [stats]) {
186-
expect(s.startTime).toBeGreaterThan(0);
187-
expect(s.endTime).toBeGreaterThan(0);
188-
s.endTime = new Date("04/20/1970, 12:42:42 PM").getTime();
189-
s.startTime = s.endTime - 1234;
190-
}
191-
let actual = stats.toString(toStringOptions);
192-
expect(typeof actual).toBe("string");
193-
if (!hasColorSetting) {
194-
actual = stderr.toString() + actual;
195-
actual = actual
196-
.replace(/\u001B\[[0-9;]*m/g, "")
197-
.replace(/[.0-9]+(\s?ms)/g, "X$1");
198-
} else {
199-
actual = stderr.toStringRaw() + actual;
193+
// mock timestamps
194+
for (const { compilation: s } of stats.stats
195+
? stats.stats
196+
: [stats]) {
197+
expect(s.startTime).toBeGreaterThan(0);
198+
expect(s.endTime).toBeGreaterThan(0);
199+
s.endTime = new Date("04/20/1970, 12:42:42 PM").getTime();
200+
s.startTime = s.endTime - 1234;
201+
}
202+
let actual = stats.toString(toStringOptions);
203+
expect(typeof actual).toBe("string");
204+
if (!hasColorSetting) {
205+
actual = stderr.toString() + actual;
206+
actual = actual
207+
.replace(/\u001B\[[0-9;]*m/g, "")
208+
.replace(/[.0-9]+(\s?ms)/g, "X$1");
209+
} else {
210+
actual = stderr.toStringRaw() + actual;
211+
actual = actual
212+
.replace(/\u001B\[1m\u001B\[([0-9;]*)m/g, "<CLR=$1,BOLD>")
213+
.replace(/\u001B\[1m/g, "<CLR=BOLD>")
214+
.replace(/\u001B\[39m\u001B\[22m/g, "</CLR>")
215+
.replace(/\u001B\[([0-9;]*)m/g, "<CLR=$1>")
216+
.replace(/[.0-9]+(<\/CLR>)?(\s?ms)/g, "X$1$2");
217+
}
218+
// cspell:ignore Xdir
200219
actual = actual
201-
.replace(/\u001B\[1m\u001B\[([0-9;]*)m/g, "<CLR=$1,BOLD>")
202-
.replace(/\u001B\[1m/g, "<CLR=BOLD>")
203-
.replace(/\u001B\[39m\u001B\[22m/g, "</CLR>")
204-
.replace(/\u001B\[([0-9;]*)m/g, "<CLR=$1>")
205-
.replace(/[.0-9]+(<\/CLR>)?(\s?ms)/g, "X$1$2");
206-
}
207-
// cspell:ignore Xdir
208-
const testPath = path.join(base, testName);
209-
actual = actual
210-
.replace(/\r\n?/g, "\n")
211-
.replace(/webpack [^ )]+(\)?) compiled/g, "webpack x.x.x$1 compiled")
212-
.replace(new RegExp(quoteMeta(testPath), "g"), `Xdir/${testName}`)
213-
.replace(/(\w)\\(\w)/g, "$1/$2")
214-
.replace(/, additional resolving: X ms/g, "")
215-
.replace(/Unexpected identifier '.+?'/g, "Unexpected identifier")
216-
.replace(/[.0-9]+(\s?(bytes|KiB|MiB|GiB))/g, "X$1")
217-
.replace(
218-
/ms\s\([0-9a-f]{6,32}\)|(?!\d+-)[0-9a-f-]{6,32}\./g,
219-
(match) => `${match.replace(/[0-9a-f]/g, "X")}`
220-
)
221-
// Normalize stack traces between Jest v27 and v30
222-
// Jest v27: at Object.<anonymous>.module.exports
223-
// Jest v30: at Object.module.exports
224-
.replace(/Object\.<anonymous>\./g, "Object.");
225-
expect(actual).toMatchSnapshot();
220+
.replace(/\r\n?/g, "\n")
221+
.replace(
222+
/webpack [^ )]+(\)?) compiled/g,
223+
"webpack x.x.x$1 compiled"
224+
)
225+
.replace(
226+
new RegExp(quoteMeta(testDirectory), "g"),
227+
`Xdir/${testName}`
228+
)
229+
.replace(/(\w)\\(\w)/g, "$1/$2")
230+
.replace(/, additional resolving: X ms/g, "")
231+
.replace(/Unexpected identifier '.+?'/g, "Unexpected identifier")
232+
.replace(/[.0-9]+(\s?(bytes|KiB|MiB|GiB))/g, "X$1")
233+
.replace(
234+
/ms\s\([0-9a-f]{6,32}\)|(?!\d+-)[0-9a-f-]{6,32}\./g,
235+
(match) => `${match.replace(/[0-9a-f]/g, "X")}`
236+
)
237+
// Normalize stack traces between Jest v27 and v30
238+
// Jest v27: at Object.<anonymous>.module.exports
239+
// Jest v30: at Object.module.exports
240+
.replace(/Object\.<anonymous>\./g, "Object.");
241+
expect(actual).toMatchSnapshot();
226242

227-
if (testConfig.validate) {
228-
try {
229-
testConfig.validate(stats, stderr.toString());
230-
} catch (err) {
231-
done(err);
232-
return;
243+
if (testConfig.validate) {
244+
try {
245+
testConfig.validate(stats, stderr.toString());
246+
} catch (err) {
247+
done(err);
248+
return;
249+
}
233250
}
234-
}
235251

236-
done();
252+
done();
253+
});
237254
});
238255
});
239256
}

0 commit comments

Comments
 (0)