Open jimsnab opened 3 years ago
I found a workaround. It's essentially
stdout
and count the number of write() bytesThis code could be improved.
const tty = require('tty');
function hookStdOut() {
if (process.stdout.isTTY) {
process.stdout.writeLength = process.stdout.bytesWritten;
process.stdout.oldWrite = process.stdout.write;
process.stdout.write = (data, encoding = 'utf8', cb = undefined) => {
process.stdout.writeLength += Buffer.byteLength(data, encoding);
return process.stdout.oldWrite(data, encoding, cb);
}
}
}
hookStdOut();
function flushStdOut(callback) {
if (process.stdout.isTTY) {
const waiter = function(innerCallback) {
if (process.stdout.bytesWritten >= process.stdout.writeLength) {
innerCallback();
} else {
setTimeout(waiter, 1, innerCallback);
}
}
waiter(callback);
} else {
callback();
}
}
const logOptions = {
writer: text => {
process.stdout.write(`${text}\n`);
this.finishedCount++;
}
};
const log = require('simple-node-logger').createSimpleLogger(logOptions);
log.originalLog = log.log;
log.startedCount = 0;
log.finishedCount = 0;
log.log = (level, message) => { log.startedCount++; log.originalLog(level, message); }
// Add a flush() API to the log
log.flush = function () {
return new Promise(resolve => {
const waiter = function (logInstance) {
// wait for log writer(s) to write, then flush stdout
if (process.stdout.bytesWritten < logInstance.bytesLogged) {
return setTimeout(waiter, 1, logInstance);
} else {
flushStdOut(resolve);
}
};
waiter(log);
});
};
// test function
function delay(ms) {
return new Promise(resolve => {
setTimeout(resolve, ms);
});
}
// test
describe("jest logging", () => {
it("logs some messages", async () => {
for (let i = 0; i < 300; i++) {
log.info(`Message ${i} A started=${log.startedCount} finished=${log.finishedCount}`);
log.info(`Message ${i} B started=${log.startedCount} finished=${log.finishedCount}`);
await delay(1);
}
await log.flush();
});
});
When using simple-node-logger and jest, the output from jest in stderr might land somewhere in the middle of log output. It requires a sufficient number of log messages.
Jest code:
Results in
Cannot log after tests are done. Did you forget to wait for something async in your test?
In trying to work around the error above, I ended up with a different undesirable behavior: stdout messages are delayed, and Jest's stderr messages land in the middle of output. (Adjust "jest logging" for loop count depending on the speed of your computer.)
Result: (partial output)
To solve this, simple-node-logger needs a proper flush() function.