From 908c738a5c69ea9d951908c679594acdc4a238e5 Mon Sep 17 00:00:00 2001 From: Gleb Bahmutov Date: Thu, 19 Sep 2019 13:49:57 -0400 Subject: [PATCH] cli: fix the STDIN pipe on Windows (#5045) * cli: pipe stdin * uggh, here is the actual change * update cli unit tests * add unit test --- cli/lib/exec/spawn.js | 20 +++++++++++++++++--- cli/test/lib/exec/spawn_spec.js | 8 +++++++- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/cli/lib/exec/spawn.js b/cli/lib/exec/spawn.js index dbb9a6507473..2f235f418a68 100644 --- a/cli/lib/exec/spawn.js +++ b/cli/lib/exec/spawn.js @@ -135,12 +135,25 @@ module.exports = { child.on('close', resolve) child.on('error', reject) - child.stdin && child.stdin.pipe(process.stdin) - child.stdout && child.stdout.pipe(process.stdout) + // if stdio options is set to 'pipe', then + // we should set up pipes: + // process STDIN (read stream) => child STDIN (writeable) + // child STDOUT => process STDOUT + // child STDERR => process STDERR with additional filtering + if (child.stdin) { + debug('piping process STDIN into child STDIN') + process.stdin.pipe(child.stdin) + } + + if (child.stdout) { + debug('piping child STDOUT to process STDOUT') + child.stdout.pipe(process.stdout) + } // if this is defined then we are manually piping for linux // to filter out the garbage - child.stderr && + if (child.stderr) { + debug('piping child STDERR to process STDERR') child.stderr.on('data', (data) => { const str = data.toString() @@ -158,6 +171,7 @@ module.exports = { // else pass it along! process.stderr.write(data) }) + } // https://github.com/cypress-io/cypress/issues/1841 // In some versions of node, it will throw on windows diff --git a/cli/test/lib/exec/spawn_spec.js b/cli/test/lib/exec/spawn_spec.js index 75f46650ef5b..9cfd1e64d1b3 100644 --- a/cli/test/lib/exec/spawn_spec.js +++ b/cli/test/lib/exec/spawn_spec.js @@ -39,7 +39,10 @@ describe('lib/exec/spawn', function () { }, } - sinon.stub(process, 'stdin').value(new EE) + // process.stdin is both an event emitter and a readable stream + this.processStdin = new EE() + this.processStdin.pipe = sinon.stub().returns(undefined) + sinon.stub(process, 'stdin').value(this.processStdin) sinon.stub(cp, 'spawn').returns(this.spawnedProcess) sinon.stub(xvfb, 'start').resolves() sinon.stub(xvfb, 'stop').resolves() @@ -292,6 +295,9 @@ describe('lib/exec/spawn', function () { return spawn.start() .then(() => { expect(cp.spawn.firstCall.args[2].stdio).to.deep.eq('pipe') + // parent process STDIN was piped to child process STDIN + expect(this.processStdin.pipe, 'process.stdin').to.have.been.calledOnce + .and.to.have.been.calledWith(this.spawnedProcess.stdin) }) })