refactor test, evenly truncate details text, properly handle undefined stderr.columns

This commit is contained in:
Ben Kucera 2019-06-04 12:33:55 -04:00
parent e7c2b7d813
commit 7aefa64b0a
4 changed files with 130 additions and 106 deletions

View File

@ -18,8 +18,8 @@ const createDefaultHandler = profile => {
const defaultHandler = (percentage, msg, ...args) => {
let state = msg;
const details = args;
const maxLength = Math.min(process.stderr.columns, 40);
const details = args.filter(v => v.length);
const maxLineLength = process.stderr.columns || Infinity;
if (percentage < 1) {
percentage = Math.floor(percentage * 100);
msg = `${percentage}% ${msg}`;
@ -29,12 +29,28 @@ const createDefaultHandler = profile => {
if (percentage < 10) {
msg = ` ${msg}`;
}
for (let detail of details) {
if (!detail) continue;
if (msg.length + detail.length > maxLength) {
detail = `${detail.substr(-(maxLength - msg.length - 2))}`;
if (details.length) {
const maxTotalDetailsLength = maxLineLength - msg.length;
const totalDetailsLength = details.reduce(
(a, b) => a + b.length,
details.length // account for added space before each detail text
);
const maxDetailLength =
totalDetailsLength < maxTotalDetailsLength
? Infinity
: Math.floor(maxTotalDetailsLength / details.length);
for (let detail of details) {
if (!detail) continue;
if (detail.length + 1 > maxDetailLength) {
const truncatePrefix = "...";
detail = `${truncatePrefix}${detail.substr(
-(maxDetailLength - truncatePrefix.length - 1)
)}`;
}
msg += ` ${detail}`;
}
msg += ` ${detail}`;
}
}
if (profile) {
@ -56,7 +72,7 @@ const createDefaultHandler = profile => {
}
if (lastMessage !== msg) {
goToLineStart(msg);
msg = msg.substring(0, maxLength);
msg = msg.substring(0, maxLineLength);
process.stderr.write(msg);
lastMessage = msg;
}

View File

@ -1,9 +1,61 @@
"use strict";
const _ = require("lodash");
const path = require("path");
const MemoryFs = require("memory-fs");
const webpack = require("../");
const { Stdio, RunCompilerAsync } = require("./support/utils");
const captureStdio = require("./helpers/captureStdio");
describe("ProgressPlugin", function() {
let _env;
let stderr;
beforeEach(() => {
_env = process.env;
stderr = captureStdio(process.stderr);
});
afterEach(() => {
process.env = _env;
stderr && stderr.restore();
});
it("should not contain NaN as a percentage when it is applied to MultiCompiler", () => {
const compiler = createMultiCompiler();
return RunCompilerAsync(compiler).then(() => {
expect(stderr.toString()).toContain("%");
expect(stderr.toString()).not.toContain("NaN");
});
});
it("should not print lines longer than stderr.columns", () => {
const compiler = createSimpleCompiler();
process.stderr.columns = 30;
return RunCompilerAsync(compiler).then(() => {
const logs = getLogs(stderr.toString());
expect(logs.length).toBeGreaterThan(20);
logs.forEach(log => expect(log.length).toBeLessThanOrEqual(30));
expect(logs).toContain(
" 10% building ...ules ...tive",
"trims each detail string equally"
);
});
});
it("should handle when stderr.columns is undefined", () => {
const compiler = createSimpleCompiler();
process.stderr.columns = undefined;
return RunCompilerAsync(compiler).then(() => {
const logs = getLogs(stderr.toString());
expect(logs.length).toBeGreaterThan(20);
expect(_.maxBy(logs, "length").length).toBeGreaterThan(50);
});
});
});
const createMultiCompiler = () => {
const compiler = webpack([
@ -17,65 +69,34 @@ const createMultiCompiler = () => {
}
]);
compiler.outputFileSystem = new MemoryFs();
new webpack.ProgressPlugin().apply(compiler);
return compiler;
};
describe("ProgressPlugin", function() {
let _env;
let stderr;
beforeEach(() => {
_env = process.env;
stderr = Stdio.capture(process.stderr);
});
afterEach(() => {
process.env = _env;
stderr && stderr.restore();
const createSimpleCompiler = () => {
const compiler = webpack({
context: path.join(__dirname, "fixtures"),
entry: "./a.js"
});
it("should not contain NaN as a percentage when it is applied to MultiCompiler", () => {
const compiler = createMultiCompiler();
compiler.outputFileSystem = new MemoryFs();
new webpack.ProgressPlugin().apply(compiler);
new webpack.ProgressPlugin().apply(compiler);
return RunCompilerAsync(compiler).then(() => {
expect(stderr.toString()).not.toContain("NaN");
return compiler;
};
const getLogs = logsStr => logsStr.split(/\u0008+/).filter(v => !(v === " "));
const RunCompilerAsync = compiler =>
new Promise((resolve, reject) => {
compiler.run(err => {
if (err) {
reject(err);
} else {
resolve();
}
});
});
it("should not print lines longer than stderr.columns or 40", () => {
const compiler = webpack({
context: path.join(__dirname, "fixtures"),
entry: "./a.js"
});
compiler.outputFileSystem = new MemoryFs();
new webpack.ProgressPlugin().apply(compiler);
process.stderr.columns = 10;
return RunCompilerAsync(compiler)
.then(() => {
const logs = stderr
.toString()
.split(/+/)
.filter(v => !(v === " "));
expect(logs.length).toBeGreaterThan(20);
logs.map(v => expect(v.length).toBeLessThanOrEqual(10));
process.stderr.columns = undefined;
})
.then(() => RunCompilerAsync(compiler))
.then(() => {
const logs = stderr
.toString()
.split(/+/)
.filter(v => !(v === " "));
expect(logs.length).toBeGreaterThan(20);
logs.map(v => expect(v.length).toBeLessThanOrEqual(40));
});
});
});

View File

@ -0,0 +1,31 @@
const stripAnsi = require("strip-ansi");
module.exports = stdio => {
let logs = [];
const write = stdio.write;
stdio.write = function(str) {
logs.push(str);
write.apply(this, arguments);
};
return {
data: logs,
reset: () => (logs = []),
toString: () => {
return logs.map(v => stripAnsi(v)).join("");
},
toStringRaw: () => {
return logs.join("");
},
restore() {
stdio.write = write;
}
};
};

View File

@ -1,44 +0,0 @@
const stripAnsi = require("strip-ansi");
module.exports = {
Stdio: {
capture(stdio) {
const logs = [];
const write = stdio.write;
stdio.write = function(str) {
logs.push(str);
write.apply(this, arguments);
};
return {
data: logs,
toString: () => {
return logs.map(v => stripAnsi(v)).join("");
},
toStringRaw: () => {
logs.join("");
},
restore() {
stdio.write = write;
}
};
}
},
RunCompilerAsync: compiler =>
new Promise((resolve, reject) => {
compiler.run(err => {
if (err) {
reject(err);
} else {
resolve();
}
});
})
};