Skip to content

Commit

Permalink
Temporarily uncork report stream when clearing spinner
Browse files Browse the repository at this point in the history
The spinner is not cleared while the stream is corked, which then
corrupts the printing of stdout / stderr chunks received from the test
processes.

Fixes #2541
  • Loading branch information
novemberborn committed Aug 1, 2020
1 parent 8d03e1d commit 5ddc9fd
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 23 deletions.
60 changes: 50 additions & 10 deletions lib/reporters/default.js
Expand Up @@ -18,7 +18,6 @@ const colors = require('./colors');
const formatSerializedError = require('./format-serialized-error');
const improperUsageMessages = require('./improper-usage-messages');
const prefixTitle = require('./prefix-title');
const whileCorked = require('./while-corked');

const nodeInternals = require('stack-utils').nodeInternals();

Expand Down Expand Up @@ -97,6 +96,48 @@ class LineWriterWithSpinner extends LineWriter {
}
}

function manageCorking(stream) {
let corked = false;
const cork = () => {
corked = true;
stream.cork();
};

const uncork = () => {
corked = false;
stream.uncork();
};

return {
decorateFlushingWriter(fn) {
return function (...args) {
if (corked) {
stream.uncork();
}

try {
return fn.apply(this, args);
} finally {
if (corked) {
stream.cork();
}
}
};
},

decorateWriter(fn) {
return function (...args) {
cork();
try {
return fn.apply(this, args);
} finally {
uncork();
}
};
}
};
}

class Reporter {
constructor({
verbose,
Expand All @@ -112,13 +153,16 @@ class Reporter {
this.stdStream = stdStream;
this.watching = watching;
this.relativeFile = file => path.relative(projectDir, file);
this.consumeStateChange = whileCorked(this.reportStream, this.consumeStateChange);

const {decorateWriter, decorateFlushingWriter} = manageCorking(this.reportStream);
this.consumeStateChange = decorateWriter(this.consumeStateChange);
this.endRun = decorateWriter(this.endRun);

if (this.verbose) {
this.durationThreshold = durationThreshold || 100;
this.spinner = null;
this.clearSpinner = () => {};
this.lineWriter = new LineWriter(this.reportStream);
this.endRun = whileCorked(this.reportStream, this.endRun);
} else {
this.spinner = ora({
isEnabled: true,
Expand All @@ -128,8 +172,8 @@ class Reporter {
spinner: spinner || (process.platform === 'win32' ? 'line' : 'dots'),
stream: reportStream
});
this.clearSpinner = decorateFlushingWriter(this.spinner.clear.bind(this.spinner));
this.lineWriter = new LineWriterWithSpinner(this.reportStream, this.spinner);
this.endRun = whileCorked(this.reportStream, whileCorked(this.lineWriter, this.endRun));
}

this.reset();
Expand Down Expand Up @@ -362,9 +406,7 @@ class Reporter {

case 'worker-stderr': {
// Forcibly clear the spinner, writing the chunk corrupts the TTY.
if (this.spinner !== null) {
this.spinner.clear();
}
this.clearSpinner();

this.stdStream.write(event.chunk);
// If the chunk does not end with a linebreak, *forcibly* write one to
Expand All @@ -386,9 +428,7 @@ class Reporter {

case 'worker-stdout': {
// Forcibly clear the spinner, writing the chunk corrupts the TTY.
if (this.spinner !== null) {
this.spinner.clear();
}
this.clearSpinner();

this.stdStream.write(event.chunk);
// If the chunk does not end with a linebreak, *forcibly* write one to
Expand Down
13 changes: 0 additions & 13 deletions lib/reporters/while-corked.js

This file was deleted.

0 comments on commit 5ddc9fd

Please sign in to comment.