Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(server): add stdin for API #2106

Closed
wants to merge 40 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
abcdf20
feat(server): add stdin for api
knagaitsev Jul 6, 2019
aa26a3b
test(server): change cli test to see if time out without stdin
knagaitsev Jul 9, 2019
821a75a
test(client): check for fail instead of timedOut
knagaitsev Jul 9, 2019
e7b4d36
test(client): loosen failure restriction on cli with no stdin
knagaitsev Jul 9, 2019
98ccd7b
test(server): update execa
knagaitsev Jul 9, 2019
b93bdeb
test(server): switch from waiting for time out to killing child process
knagaitsev Jul 10, 2019
f32cfe1
test(server): downgrade execa
knagaitsev Jul 10, 2019
8c23ede
test(cli): temporarily remove stdin cli tests
knagaitsev Jul 12, 2019
c95ba88
test(cli): switch to spawn for stdin test
knagaitsev Jul 12, 2019
33ff4f6
test(server): changed env for cli tests
knagaitsev Jul 14, 2019
87bf035
test(cli): switch waiting for close to exit event
knagaitsev Jul 14, 2019
c93b1f9
test(cli): added error event listener for debugging
knagaitsev Jul 14, 2019
fcca53e
test(cli): remove sigterm test
knagaitsev Jul 14, 2019
6bf64de
test(cli): disable stdin cli tests temporarily
knagaitsev Jul 15, 2019
404f983
test(options): remove stdin options test temporarily
knagaitsev Jul 16, 2019
93fca66
test(options): add stdin end emit
knagaitsev Jul 16, 2019
948a724
test(options): move stdin end emit to right after server creation
knagaitsev Jul 16, 2019
02567e3
test(cli): remove stdin cli tests temporarily again
knagaitsev Jul 16, 2019
5a38b8f
test(options): remove stdin option test again temporarily
knagaitsev Jul 16, 2019
33fb577
test(options): remove end emit
knagaitsev Jul 16, 2019
ff5d730
test(server): remove some stdin end emits
knagaitsev Jul 16, 2019
5cbc2a4
test(server): add stdin pause next to end emit
knagaitsev Jul 16, 2019
d849568
test(cli): switch back to execa from spawn
knagaitsev Jul 16, 2019
d182b07
test(cli): upgrade execa
knagaitsev Jul 16, 2019
17fddfc
test(cli): switch back to spawn
knagaitsev Jul 16, 2019
d670177
test(cli): downgrade execa again
knagaitsev Jul 16, 2019
2bc9387
test(server): forcefully remove stdin end listeners
knagaitsev Jul 17, 2019
0c9f4bb
fix(package): fix package lock
knagaitsev Jul 23, 2019
ddc12d3
fix(package): fix package lock again
knagaitsev Jul 23, 2019
48a40b4
test(server): skip new stdin tests
knagaitsev Jul 23, 2019
fcef89d
test(server): removed stdin tests entirely
knagaitsev Jul 24, 2019
2634594
test(server): remove cli test
knagaitsev Jul 24, 2019
5db844a
test(server): remove options test
knagaitsev Jul 24, 2019
b3b3299
test(server): add back stdin files
knagaitsev Jul 24, 2019
959c0ed
test(server): only cli stdin
knagaitsev Jul 24, 2019
66cd1df
test(server): add handle stdin helper only
knagaitsev Jul 24, 2019
bf90582
test(server): add stdin option test only
knagaitsev Jul 24, 2019
28a7073
test(server): only handle stdin
knagaitsev Jul 24, 2019
ec41502
test(server): move stdin pause after a delay following stdin resume
knagaitsev Jul 24, 2019
b35e8ac
test(options): removed exit mock
knagaitsev Jul 24, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions lib/Server.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ const createDomain = require('./utils/createDomain');
const runBonjour = require('./utils/runBonjour');
const routes = require('./utils/routes');
const getSocketServerImplementation = require('./utils/getSocketServerImplementation');
const handleStdin = require('./utils/handleStdin');
const schema = require('./options.json');

// Workaround for node ^8.6.0, ^9.0.0
Expand All @@ -59,6 +60,8 @@ class Server {
this.compiler = compiler;
this.options = options;

handleStdin(options);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hm, why we need it here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@evilebottnawi Do you think no helper would be better? I just thought having helper would be cleaner

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think we need this inside server file, it is logic for CLI only


this.log = _log || createLogger(options);

if (this.options.serverMode !== undefined) {
Expand Down
4 changes: 4 additions & 0 deletions lib/options.json
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,9 @@
}
]
},
"stdin": {
"type": "boolean"
},
"useLocalIp": {
"type": "boolean"
},
Expand Down Expand Up @@ -447,6 +450,7 @@
"socket": "should be {String} (https://webpack.js.org/configuration/dev-server/#devserversocket)",
"staticOptions": "should be {Object} (https://webpack.js.org/configuration/dev-server/#devserverstaticoptions)",
"stats": "should be {Object|Boolean} (https://webpack.js.org/configuration/dev-server/#devserverstats-)",
"stdin": "should be {Boolean} (https://webpack.js.org/configuration/dev-server/#devserverstdin)",
"useLocalIp": "should be {Boolean} (https://webpack.js.org/configuration/dev-server/#devserveruselocalip)",
"warn": "should be {Function}",
"watchContentBase": "should be {Boolean} (https://webpack.js.org/configuration/dev-server/#devserverwatchcontentbase)",
Expand Down
7 changes: 1 addition & 6 deletions lib/utils/createConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,7 @@ function createConfig(config, argv, { port }) {
}

if (argv.stdin) {
process.stdin.on('end', () => {
// eslint-disable-next-line no-process-exit
process.exit(0);
});

process.stdin.resume();
options.stdin = true;
}

// TODO https://github.com/webpack/webpack-dev-server/issues/616 (v4)
Expand Down
16 changes: 16 additions & 0 deletions lib/utils/handleStdin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
'use strict';

function handleStdin(options) {
if (options.stdin) {
// listening for this event only once makes testing easier,
// since it prevents event listeners from hanging open
process.stdin.once('end', () => {
// eslint-disable-next-line no-process-exit
process.exit(0);
});

process.stdin.resume();
}
}

module.exports = handleStdin;
47 changes: 47 additions & 0 deletions test/cli/cli.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,53 @@ describe('CLI', () => {
.catch(done);
});

it('without --stdin, with stdin "end" event should time out', (done) => {
const configPath = resolve(
__dirname,
'../fixtures/simple-config/webpack.config.js'
);
const childProcess = testBin(false, configPath, true);

setTimeout(() => {
// this is meant to confirm that it does not have any effect on the running process
// since options.stdin is not enabled
childProcess.stdin.emit('end');
childProcess.stdin.pause();
}, 500);

setTimeout(() => {
childProcess.kill();
}, 1000);

childProcess.once('exit', () => {
expect(childProcess.killed).toBeTruthy();
done();
});
});

it('--stdin, with "end" event should exit without time out', (done) => {
const configPath = resolve(
__dirname,
'../fixtures/simple-config/webpack.config.js'
);
const childProcess = testBin('--stdin', configPath);

setTimeout(() => {
childProcess.stdin.emit('end');
childProcess.stdin.pause();
}, 500);

childProcess
.then((output) => {
childProcess.stdin.removeAllListeners('end');
expect(output.code).toEqual(0);
expect(output.timedOut).toBeFalsy();
expect(output.killed).toBeFalsy();
done();
})
.catch(done);
});

it('should accept the promise function of webpack.config.js', (done) => {
testBin(
false,
Expand Down
19 changes: 16 additions & 3 deletions test/helpers/test-bin.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use strict';

const path = require('path');
const { spawn } = require('child_process');
const execa = require('execa');

const webpackDevServerPath = path.resolve(
Expand All @@ -12,9 +13,12 @@ const basicConfigPath = path.resolve(
'../fixtures/cli/webpack.config.js'
);

function testBin(testArgs, configPath) {
function testBin(testArgs, configPath, useSpawn) {
const cwd = process.cwd();
const env = process.env.NODE_ENV;
const env = {
NODE_ENV: process.env.NODE_ENV,
PATH: process.env.PATH,
};

if (!configPath) {
configPath = basicConfigPath;
Expand All @@ -28,7 +32,16 @@ function testBin(testArgs, configPath) {

const args = [webpackDevServerPath, '--config', configPath].concat(testArgs);

return execa('node', args, { cwd, env, timeout: 10000 });
const opts = { cwd, env, timeout: 10000 };
let execLib = execa;
// use Node's spawn as a workaround for execa issues
// https://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options
if (useSpawn) {
execLib = spawn;
delete opts.timeout;
}

return execLib('node', args, opts);
}

module.exports = testBin;
4 changes: 4 additions & 0 deletions test/options.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,10 @@ describe('options', () => {
],
failure: ['whoops!', null],
},
stdin: {
success: [false],
failure: [''],
},
useLocalIp: {
success: [false],
failure: [''],
Expand Down
1 change: 1 addition & 0 deletions test/ports-map.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ const portsList = {
'progress-option': 1,
'profile-option': 1,
Iframe: 1,
'stdin-option': 1,
};

let startPort = 8079;
Expand Down
65 changes: 65 additions & 0 deletions test/server/stdin-option.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
'use strict';

const config = require('../fixtures/simple-config/webpack.config');
const testServer = require('../helpers/test-server');
const port = require('../ports-map')['stdin-option'];

describe('stdin', () => {
// eslint-disable-next-line no-unused-vars
let server;
let exitSpy;

beforeAll(() => {
exitSpy = jest.spyOn(process, 'exit').mockImplementation(() => {});
});

afterEach((done) => {
server = null;
exitSpy.mockReset();
process.stdin.removeAllListeners('end');
testServer.close(done);
});

describe('enabled', () => {
beforeAll((done) => {
server = testServer.start(
config,
{
port,
stdin: true,
},
done
);
});

it('should exit process', (done) => {
process.stdin.emit('end');
setTimeout(() => {
process.stdin.pause();
expect(exitSpy.mock.calls[0]).toEqual([0]);
done();
}, 1000);
});
});

describe('disabled (default)', () => {
beforeAll((done) => {
server = testServer.start(
config,
{
port,
},
done
);
});

it('should not exit process', (done) => {
process.stdin.emit('end');
setTimeout(() => {
process.stdin.pause();
expect(exitSpy.mock.calls.length).toEqual(0);
done();
}, 1000);
});
});
});
42 changes: 42 additions & 0 deletions test/server/utils/handleStdin.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
'use strict';

const handleStdin = require('../../../lib/utils/handleStdin');

describe('handleStdin', () => {
let exitSpy;

beforeAll(() => {
exitSpy = jest.spyOn(process, 'exit').mockImplementation(() => {});
});

afterEach(() => {
process.stdin.removeAllListeners('end');
exitSpy.mockReset();
});

describe('enabled', () => {
it('should exit process', (done) => {
handleStdin({
stdin: true,
});
process.stdin.emit('end');
setTimeout(() => {
process.stdin.pause();
expect(exitSpy.mock.calls[0]).toEqual([0]);
done();
}, 1000);
});
});

describe('disabled (default)', () => {
it('should not exit process', (done) => {
handleStdin({});
process.stdin.emit('end');
setTimeout(() => {
process.stdin.pause();
expect(exitSpy.mock.calls.length).toEqual(0);
done();
}, 1000);
});
});
});