diff --git a/README.md b/README.md index edd225f700..57ac812ef9 100644 --- a/README.md +++ b/README.md @@ -130,6 +130,7 @@ Options: --https-key Path to an SSL key. --https-pfx Path to an SSL pfx file. --https-cert Path to an SSL certificate. + --ipc [value] Listen to a unix socket. https://webpack.js.org/configuration/dev-server/#devserveripc --live-reload Enables reload/refresh the page(s) when file changes are detected (enabled by default). https://webpack.js.org/configuration/dev-server/#devserverlivereload --no-live-reload Negative 'live-reload' option. diff --git a/bin/cli-flags.js b/bin/cli-flags.js index 7734906d58..0908c5eaac 100644 --- a/bin/cli-flags.js +++ b/bin/cli-flags.js @@ -510,6 +510,29 @@ module.exports = { simpleType: 'string', multiple: false, }, + ipc: { + configs: [ + { + type: 'string', + multiple: false, + description: + 'Listen to a unix socket. https://webpack.js.org/configuration/dev-server/#devserveripc', + path: 'ipc', + }, + { + type: 'enum', + values: [true], + multiple: false, + description: + 'Listen to a unix socket. https://webpack.js.org/configuration/dev-server/#devserveripc', + path: 'ipc', + }, + ], + description: + 'Listen to a unix socket. https://webpack.js.org/configuration/dev-server/#devserveripc', + simpleType: 'string', + multiple: false, + }, 'live-reload': { configs: [ { diff --git a/lib/Server.js b/lib/Server.js index bfb141f68d..80eb1fe858 100644 --- a/lib/Server.js +++ b/lib/Server.js @@ -1,5 +1,6 @@ 'use strict'; +const net = require('net'); const path = require('path'); const fs = require('fs'); const url = require('url'); @@ -759,94 +760,105 @@ class Server { }; const useColor = getColorsOption(getCompilerConfigArray(this.compiler)); - const protocol = this.options.https ? 'https' : 'http'; - const { address, port } = this.server.address(); - const prettyPrintUrl = (newHostname) => - url.format({ protocol, hostname: newHostname, port, pathname: '/' }); - - let server; - let localhost; - let loopbackIPv4; - let loopbackIPv6; - let networkUrlIPv4; - let networkUrlIPv6; - - if (this.options.host) { - if (this.options.host === 'localhost') { - localhost = prettyPrintUrl('localhost'); - } else { - let isIP; - try { - isIP = ipaddr.parse(this.options.host); - } catch (error) { - // Ignore - } + if (this.options.ipc) { + this.logger.info(`Project is running at: "${this.server.address()}"`); + } else { + const protocol = this.options.https ? 'https' : 'http'; + const { address, port } = this.server.address(); + const prettyPrintUrl = (newHostname) => + url.format({ protocol, hostname: newHostname, port, pathname: '/' }); + + let server; + let localhost; + let loopbackIPv4; + let loopbackIPv6; + let networkUrlIPv4; + let networkUrlIPv6; + + if (this.options.host) { + if (this.options.host === 'localhost') { + localhost = prettyPrintUrl('localhost'); + } else { + let isIP; - if (!isIP) { - server = prettyPrintUrl(this.options.host); + try { + isIP = ipaddr.parse(this.options.host); + } catch (error) { + // Ignore + } + + if (!isIP) { + server = prettyPrintUrl(this.options.host); + } } } - } - const parsedIP = ipaddr.parse(address); + const parsedIP = ipaddr.parse(address); - if (parsedIP.range() === 'unspecified') { - localhost = prettyPrintUrl('localhost'); + if (parsedIP.range() === 'unspecified') { + localhost = prettyPrintUrl('localhost'); - const networkIPv4 = internalIp.v4.sync(); + const networkIPv4 = internalIp.v4.sync(); - if (networkIPv4) { - networkUrlIPv4 = prettyPrintUrl(networkIPv4); - } + if (networkIPv4) { + networkUrlIPv4 = prettyPrintUrl(networkIPv4); + } - const networkIPv6 = internalIp.v6.sync(); + const networkIPv6 = internalIp.v6.sync(); - if (networkIPv6) { - networkUrlIPv6 = prettyPrintUrl(networkIPv6); - } - } else if (parsedIP.range() === 'loopback') { - if (parsedIP.kind() === 'ipv4') { - loopbackIPv4 = prettyPrintUrl(parsedIP.toString()); - } else if (parsedIP.kind() === 'ipv6') { - loopbackIPv6 = prettyPrintUrl(parsedIP.toString()); + if (networkIPv6) { + networkUrlIPv6 = prettyPrintUrl(networkIPv6); + } + } else if (parsedIP.range() === 'loopback') { + if (parsedIP.kind() === 'ipv4') { + loopbackIPv4 = prettyPrintUrl(parsedIP.toString()); + } else if (parsedIP.kind() === 'ipv6') { + loopbackIPv6 = prettyPrintUrl(parsedIP.toString()); + } + } else { + networkUrlIPv4 = + parsedIP.kind() === 'ipv6' && parsedIP.isIPv4MappedAddress() + ? prettyPrintUrl(parsedIP.toIPv4Address().toString()) + : prettyPrintUrl(address); + + if (parsedIP.kind() === 'ipv6') { + networkUrlIPv6 = prettyPrintUrl(address); + } } - } else { - networkUrlIPv4 = - parsedIP.kind() === 'ipv6' && parsedIP.isIPv4MappedAddress() - ? prettyPrintUrl(parsedIP.toIPv4Address().toString()) - : prettyPrintUrl(address); - if (parsedIP.kind() === 'ipv6') { - networkUrlIPv6 = prettyPrintUrl(address); + this.logger.info('Project is running at:'); + + if (server) { + this.logger.info(`Server: ${colors.info(useColor, server)}`); } - } - this.logger.info('Project is running at:'); + if (localhost || loopbackIPv4 || loopbackIPv6) { + const loopbacks = [] + .concat(localhost ? [colors.info(useColor, localhost)] : []) + .concat(loopbackIPv4 ? [colors.info(useColor, loopbackIPv4)] : []) + .concat(loopbackIPv6 ? [colors.info(useColor, loopbackIPv6)] : []); - if (server) { - this.logger.info(`Server: ${colors.info(useColor, server)}`); - } + this.logger.info(`Loopback: ${loopbacks.join(', ')}`); + } - if (localhost || loopbackIPv4 || loopbackIPv6) { - const loopbacks = [] - .concat(localhost ? [colors.info(useColor, localhost)] : []) - .concat(loopbackIPv4 ? [colors.info(useColor, loopbackIPv4)] : []) - .concat(loopbackIPv6 ? [colors.info(useColor, loopbackIPv6)] : []); + if (networkUrlIPv4) { + this.logger.info( + `On Your Network (IPv4): ${colors.info(useColor, networkUrlIPv4)}` + ); + } - this.logger.info(`Loopback: ${loopbacks.join(', ')}`); - } + if (networkUrlIPv6) { + this.logger.info( + `On Your Network (IPv6): ${colors.info(useColor, networkUrlIPv6)}` + ); + } - if (networkUrlIPv4) { - this.logger.info( - `On Your Network (IPv4): ${colors.info(useColor, networkUrlIPv4)}` - ); - } + if (this.options.open) { + const openTarget = prettyPrintUrl(this.options.host || 'localhost'); - if (networkUrlIPv6) { - this.logger.info( - `On Your Network (IPv6): ${colors.info(useColor, networkUrlIPv6)}` - ); + this.openBrowser(openTarget); + } } if (this.options.static && this.options.static.length > 0) { @@ -877,15 +889,13 @@ class Server { `Broadcasting "${bonjourProtocol}" with subtype of "webpack" via ZeroConf DNS (Bonjour)` ); } - - if (this.options.open) { - const openTarget = prettyPrintUrl(this.options.host || 'localhost'); - - this.openBrowser(openTarget); - } } listen(port, hostname, fn) { + if (typeof port === 'function') { + fn = port; + } + if ( typeof port !== 'undefined' && typeof this.options.port !== 'undefined' && @@ -920,35 +930,75 @@ class Server { this.options.host = Server.getHostname(this.options.host); - return Server.getFreePort(this.options.port) - .then((foundPort) => { + const resolveFreePortOrIPC = () => { + if (this.options.ipc) { + return new Promise((resolve, reject) => { + const socket = new net.Socket(); + + socket.on('error', (error) => { + if (error.code === 'ECONNREFUSED') { + fs.unlinkSync(this.options.ipc); + + resolve(this.options.ipc); + + return; + } else if (error.code === 'ENOENT') { + resolve(this.options.ipc); + + return; + } + + reject(error); + }); + + socket.connect({ path: this.options.ipc }, () => { + throw new Error(`IPC "${this.options.ipc}" is already used`); + }); + }); + } + + return Server.getFreePort(this.options.port).then((foundPort) => { this.options.port = foundPort; + }); + }; + return resolveFreePortOrIPC() + .then(() => { this.initialize(); - return this.server.listen( - this.options.port, - this.options.host, - (error) => { - if (Boolean(this.options.hot) || this.options.liveReload) { - this.createWebSocketServer(); - } + const listenOptions = this.options.ipc + ? { path: this.options.ipc } + : { + host: this.options.host, + port: this.options.port, + }; - if (this.options.bonjour) { - this.runBonjour(); - } + return this.server.listen(listenOptions, (error) => { + if (this.options.ipc) { + // chmod 666 (rw rw rw) + const READ_WRITE = 438; - this.logStatus(); + fs.chmodSync(this.options.ipc, READ_WRITE); + } - if (fn) { - fn.call(this.server, error); - } + if (Boolean(this.options.hot) || this.options.liveReload) { + this.createWebSocketServer(); + } - if (typeof this.options.onListening === 'function') { - this.options.onListening(this); - } + if (this.options.bonjour) { + this.runBonjour(); } - ); + + this.logStatus(); + + if (fn) { + fn.call(this.server, error); + } + + if (typeof this.options.onListening === 'function') { + this.options.onListening(this); + } + }); }) .catch((error) => { if (fn) { diff --git a/lib/options.json b/lib/options.json index 0dd66202c4..d72e6ac051 100644 --- a/lib/options.json +++ b/lib/options.json @@ -308,7 +308,19 @@ ], "description": "Enables Hot Module Replacement. https://webpack.js.org/configuration/dev-server/#devserverhot" }, - + "IPC": { + "anyOf": [ + { + "type": "string", + "minLength": 1 + }, + { + "type": "boolean", + "enum": [true] + } + ], + "description": "Listen to a unix socket. https://webpack.js.org/configuration/dev-server/#devserveripc" + }, "LiveReload": { "type": "boolean", "description": "Enables reload/refresh the page(s) when file changes are detected (enabled by default). https://webpack.js.org/configuration/dev-server/#devserverlivereload" @@ -692,6 +704,9 @@ "https": { "$ref": "#/definitions/HTTPS" }, + "ipc": { + "$ref": "#/definitions/IPC" + }, "liveReload": { "$ref": "#/definitions/LiveReload" }, diff --git a/lib/utils/normalizeOptions.js b/lib/utils/normalizeOptions.js index 5e7440b58e..2234967a2d 100644 --- a/lib/utils/normalizeOptions.js +++ b/lib/utils/normalizeOptions.js @@ -219,6 +219,14 @@ function normalizeOptions(compiler, options, logger, cacheDir) { options.https.cert = options.https.cert || fakeCert; } + if (typeof options.ipc === 'boolean') { + const isWindows = process.platform === 'win32'; + const pipePrefix = isWindows ? '\\\\.\\pipe\\' : os.tmpdir(); + const pipeName = 'webpack-dev-server.sock'; + + options.ipc = path.join(pipePrefix, pipeName); + } + options.liveReload = typeof options.liveReload !== 'undefined' ? options.liveReload : true; diff --git a/package-lock.json b/package-lock.json index de87e58ff6..265456acfd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -61,6 +61,7 @@ "execa": "^5.1.1", "file-loader": "^6.2.0", "html-webpack-plugin": "^4.5.2", + "http-proxy": "^1.18.1", "husky": "^6.0.0", "jest": "^27.0.4", "less": "^4.1.1", diff --git a/package.json b/package.json index a2e88e69c1..82a1ca6380 100644 --- a/package.json +++ b/package.json @@ -81,6 +81,7 @@ "execa": "^5.1.1", "file-loader": "^6.2.0", "html-webpack-plugin": "^4.5.2", + "http-proxy": "^1.18.1", "husky": "^6.0.0", "jest": "^27.0.4", "less": "^4.1.1", diff --git a/setupTest.js b/setupTest.js index 438bcc143b..bb885657ac 100644 --- a/setupTest.js +++ b/setupTest.js @@ -1,7 +1,5 @@ 'use strict'; process.env.CHOKIDAR_USEPOLLING = true; -jest.setTimeout(180000); -// retry 3 times for flaky tests -jest.retryTimes(3); +jest.setTimeout(140000); diff --git a/test/__snapshots__/validate-options.test.js.snap.webpack4 b/test/__snapshots__/validate-options.test.js.snap.webpack4 index d056fd6a2b..eb47b2c65d 100644 --- a/test/__snapshots__/validate-options.test.js.snap.webpack4 +++ b/test/__snapshots__/validate-options.test.js.snap.webpack4 @@ -378,6 +378,27 @@ exports[`options validate should throw an error on the "https" option with '{"re -> Request for an SSL certificate." `; +exports[`options validate should throw an error on the "ipc" option with '{}' value 1`] = ` +"ValidationError: Invalid options object. Dev Server has been initialized using an options object that does not match the API schema. + - options.ipc should be one of these: + non-empty string | true + -> Listen to a unix socket. https://webpack.js.org/configuration/dev-server/#devserveripc + Details: + * options.ipc should be a non-empty string. + * options.ipc should be a true. + * options.ipc should be true." +`; + +exports[`options validate should throw an error on the "ipc" option with 'false' value 1`] = ` +"ValidationError: Invalid options object. Dev Server has been initialized using an options object that does not match the API schema. + - options.ipc should be one of these: + non-empty string | true + -> Listen to a unix socket. https://webpack.js.org/configuration/dev-server/#devserveripc + Details: + * options.ipc should be a non-empty string. + * options.ipc should be true." +`; + exports[`options validate should throw an error on the "onAfterSetupMiddleware" option with 'false' value 1`] = ` "ValidationError: Invalid options object. Dev Server has been initialized using an options object that does not match the API schema. - options.onAfterSetupMiddleware should be an instance of function. diff --git a/test/__snapshots__/validate-options.test.js.snap.webpack5 b/test/__snapshots__/validate-options.test.js.snap.webpack5 index d056fd6a2b..eb47b2c65d 100644 --- a/test/__snapshots__/validate-options.test.js.snap.webpack5 +++ b/test/__snapshots__/validate-options.test.js.snap.webpack5 @@ -378,6 +378,27 @@ exports[`options validate should throw an error on the "https" option with '{"re -> Request for an SSL certificate." `; +exports[`options validate should throw an error on the "ipc" option with '{}' value 1`] = ` +"ValidationError: Invalid options object. Dev Server has been initialized using an options object that does not match the API schema. + - options.ipc should be one of these: + non-empty string | true + -> Listen to a unix socket. https://webpack.js.org/configuration/dev-server/#devserveripc + Details: + * options.ipc should be a non-empty string. + * options.ipc should be a true. + * options.ipc should be true." +`; + +exports[`options validate should throw an error on the "ipc" option with 'false' value 1`] = ` +"ValidationError: Invalid options object. Dev Server has been initialized using an options object that does not match the API schema. + - options.ipc should be one of these: + non-empty string | true + -> Listen to a unix socket. https://webpack.js.org/configuration/dev-server/#devserveripc + Details: + * options.ipc should be a non-empty string. + * options.ipc should be true." +`; + exports[`options validate should throw an error on the "onAfterSetupMiddleware" option with 'false' value 1`] = ` "ValidationError: Invalid options object. Dev Server has been initialized using an options object that does not match the API schema. - options.onAfterSetupMiddleware should be an instance of function. diff --git a/test/cli/__snapshots__/basic.test.js.snap.webpack4 b/test/cli/__snapshots__/basic.test.js.snap.webpack4 index b48523db48..62769e4f10 100644 --- a/test/cli/__snapshots__/basic.test.js.snap.webpack4 +++ b/test/cli/__snapshots__/basic.test.js.snap.webpack4 @@ -82,6 +82,7 @@ Options: --https-key Path to an SSL key. --https-pfx Path to an SSL pfx file. --https-cert Path to an SSL certificate. + --ipc [value] Listen to a unix socket. https://webpack.js.org/configuration/dev-server/#devserveripc --live-reload Enables reload/refresh the page(s) when file changes are detected (enabled by default). https://webpack.js.org/configuration/dev-server/#devserverlivereload --no-live-reload Disables reload/refresh the page(s) when file changes are detected (enabled by default) --open [value...] Allows to configure dev server to open the browser(s) and page(s) after server had been started (set it to true to open your default browser). https://webpack.js.org/configuration/dev-server/#devserveropen diff --git a/test/cli/__snapshots__/basic.test.js.snap.webpack5 b/test/cli/__snapshots__/basic.test.js.snap.webpack5 index aed189e876..7a9fbbcb53 100644 --- a/test/cli/__snapshots__/basic.test.js.snap.webpack5 +++ b/test/cli/__snapshots__/basic.test.js.snap.webpack5 @@ -82,6 +82,7 @@ Options: --https-key Path to an SSL key. --https-pfx Path to an SSL pfx file. --https-cert Path to an SSL certificate. + --ipc [value] Listen to a unix socket. https://webpack.js.org/configuration/dev-server/#devserveripc --live-reload Enables reload/refresh the page(s) when file changes are detected (enabled by default). https://webpack.js.org/configuration/dev-server/#devserverlivereload --no-live-reload Negative 'live-reload' option. --open [value...] Allows to configure dev server to open the browser(s) and page(s) after server had been started (set it to true to open your default browser). https://webpack.js.org/configuration/dev-server/#devserveropen diff --git a/test/cli/__snapshots__/ipc-option.test.js.snap.webpack4 b/test/cli/__snapshots__/ipc-option.test.js.snap.webpack4 new file mode 100644 index 0000000000..2697c355bc --- /dev/null +++ b/test/cli/__snapshots__/ipc-option.test.js.snap.webpack4 @@ -0,0 +1,11 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`"ipc" CLI option should work using "--ipc": stderr 1`] = ` +" [webpack-dev-server] Project is running at: \\"/webpack-dev-server.sock\\" + [webpack-dev-server] Content not from webpack is served from '/public' directory" +`; + +exports[`"ipc" CLI option should work using "--ipc=": stderr 1`] = ` +" [webpack-dev-server] Project is running at: \\"/webpack-dev-server.cli.sock\\" + [webpack-dev-server] Content not from webpack is served from '/public' directory" +`; diff --git a/test/cli/__snapshots__/ipc-option.test.js.snap.webpack5 b/test/cli/__snapshots__/ipc-option.test.js.snap.webpack5 new file mode 100644 index 0000000000..2697c355bc --- /dev/null +++ b/test/cli/__snapshots__/ipc-option.test.js.snap.webpack5 @@ -0,0 +1,11 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`"ipc" CLI option should work using "--ipc": stderr 1`] = ` +" [webpack-dev-server] Project is running at: \\"/webpack-dev-server.sock\\" + [webpack-dev-server] Content not from webpack is served from '/public' directory" +`; + +exports[`"ipc" CLI option should work using "--ipc=": stderr 1`] = ` +" [webpack-dev-server] Project is running at: \\"/webpack-dev-server.cli.sock\\" + [webpack-dev-server] Content not from webpack is served from '/public' directory" +`; diff --git a/test/cli/allowedHosts-option.test.js b/test/cli/allowedHosts-option.test.js index e0b945c4f5..8004312b37 100644 --- a/test/cli/allowedHosts-option.test.js +++ b/test/cli/allowedHosts-option.test.js @@ -1,22 +1,38 @@ 'use strict'; const { testBin } = require('../helpers/test-bin'); +const port = require('../ports-map')['cli-allowed-hosts']; describe('"allowedHosts" CLI option', () => { it('should work using "--allowed-hosts auto"', async () => { - const { exitCode } = await testBin(['--allowed-hosts', 'auto']); + const { exitCode } = await testBin([ + '--allowed-hosts', + 'auto', + '--port', + port, + ]); expect(exitCode).toEqual(0); }); it('should work using "--allowed-hosts all"', async () => { - const { exitCode } = await testBin(['--allowed-hosts', 'all']); + const { exitCode } = await testBin([ + '--allowed-hosts', + 'all', + '--port', + port, + ]); expect(exitCode).toEqual(0); }); it('should work using "--allowed-hosts testhouse.com"', async () => { - const { exitCode } = await testBin(['--allowed-hosts', 'testhouse.com']); + const { exitCode } = await testBin([ + '--allowed-hosts', + 'testhouse.com', + '--port', + port, + ]); expect(exitCode).toEqual(0); }); @@ -27,6 +43,8 @@ describe('"allowedHosts" CLI option', () => { 'testhost.com', '--allowed-hosts', 'testhost1.com', + '--port', + port, ]); expect(exitCode).toEqual(0); diff --git a/test/cli/basic.test.js b/test/cli/basic.test.js index 2f4a69f46c..61411dfd5c 100644 --- a/test/cli/basic.test.js +++ b/test/cli/basic.test.js @@ -68,7 +68,9 @@ describe('basic', () => { path.resolve( __dirname, '../fixtures/promise-config/webpack.config.js' - ) + ), + '--port', + port ); expect(exitCode).toEqual(0); } catch (err) { @@ -86,7 +88,7 @@ describe('basic', () => { __dirname, '../../examples/cli/web-socket-url' ); - const cp = execa('node', [cliPath], { cwd: examplePath }); + const cp = execa('node', [cliPath, '--port', port], { cwd: examplePath }); cp.stdout.on('data', (data) => { const bits = data.toString(); @@ -109,7 +111,7 @@ describe('basic', () => { '../../bin/webpack-dev-server.js' ); const cwd = path.resolve(__dirname, '../fixtures/cli'); - const cp = execa('node', [cliPath], { cwd }); + const cp = execa('node', [cliPath, '--port', port], { cwd }); let killed = false; @@ -137,9 +139,13 @@ describe('basic', () => { __dirname, '../../examples/cli/web-socket-url' ); - const cp = execa('node', [cliPath, '--watch-options-stdin'], { - cwd: examplePath, - }); + const cp = execa( + 'node', + [cliPath, '--watch-options-stdin', '--port', port], + { + cwd: examplePath, + } + ); cp.stdout.on('data', (data) => { const bits = data.toString(); @@ -163,7 +169,11 @@ describe('basic', () => { '../../bin/webpack-dev-server.js' ); const cwd = path.resolve(__dirname, '../fixtures/cli'); - const cp = execa('node', [cliPath, '--watch-options-stdin'], { cwd }); + const cp = execa( + 'node', + [cliPath, '--watch-options-stdin', '--port', port], + { cwd } + ); let killed = false; @@ -186,7 +196,9 @@ describe('basic', () => { it('should add dev server entry points to a single entry point', async () => { const { exitCode, stdout } = await testBin( null, - './test/fixtures/dev-server/default-config.js' + './test/fixtures/dev-server/default-config.js', + '--port', + port ); expect(exitCode).toEqual(0); @@ -198,7 +210,9 @@ describe('basic', () => { async () => { const { exitCode, stdout } = await testBin( '--stats=verbose', - './test/fixtures/dev-server/multi-entry.js' + './test/fixtures/dev-server/multi-entry.js', + '--port', + port ); expect(exitCode).toEqual(0); @@ -212,7 +226,9 @@ describe('basic', () => { async () => { const { exitCode, stdout } = await testBin( null, - './test/fixtures/dev-server/empty-entry.js' + './test/fixtures/dev-server/empty-entry.js', + '--port', + port ); expect(exitCode).toEqual(0); @@ -223,7 +239,9 @@ describe('basic', () => { webpack5Test('should supports entry as descriptor', async () => { const { exitCode, stdout } = await testBin( '--stats=detailed', - './test/fixtures/entry-as-descriptor/webpack.config' + './test/fixtures/entry-as-descriptor/webpack.config', + '--port', + port ); expect(exitCode).toEqual(0); @@ -233,7 +251,9 @@ describe('basic', () => { it('should only prepends dev server entry points to "web" target', async () => { const { exitCode, stdout } = await testBin( '--target web', - './test/fixtures/dev-server/default-config.js' + './test/fixtures/dev-server/default-config.js', + '--port', + port ); expect(exitCode).toEqual(0); @@ -244,7 +264,9 @@ describe('basic', () => { it('should not prepend dev server entry points to "node" target', async () => { const { exitCode, stdout } = await testBin( '--target node', - './test/fixtures/dev-server/default-config.js' + './test/fixtures/dev-server/default-config.js', + '--port', + port ); expect(exitCode).toEqual(0); @@ -255,7 +277,9 @@ describe('basic', () => { it('should prepends the hot runtime to "node" target as well', async () => { const { exitCode, stdout } = await testBin( '--target node --hot', - './test/fixtures/dev-server/default-config.js' + './test/fixtures/dev-server/default-config.js', + '--port', + port ); expect(exitCode).toEqual(0); @@ -267,7 +291,9 @@ describe('basic', () => { async () => { const { exitCode, stdout } = await testBin( null, - './test/fixtures/dev-server/target-config.js' + './test/fixtures/dev-server/target-config.js', + '--port', + port ); expect(exitCode).toEqual(0); diff --git a/test/cli/bonjour-option.test.js b/test/cli/bonjour-option.test.js index 5c1ea50316..2d8d0a0bdd 100644 --- a/test/cli/bonjour-option.test.js +++ b/test/cli/bonjour-option.test.js @@ -1,17 +1,23 @@ 'use strict'; const { testBin, normalizeStderr } = require('../helpers/test-bin'); +const port = require('../ports-map')['cli-bonjour']; describe('"bonjour" CLI option', () => { it('should work using "--bonjour"', async () => { - const { exitCode, stderr } = await testBin(['--bonjour']); + const { exitCode, stderr } = await testBin(['--bonjour', '--port', port]); expect(exitCode).toEqual(0); expect(normalizeStderr(stderr, { ipv6: true })).toMatchSnapshot(); }); it('should work using "--bonjour and --https"', async () => { - const { exitCode, stderr } = await testBin(['--bonjour', '--https']); + const { exitCode, stderr } = await testBin([ + '--bonjour', + '--https', + '--port', + port, + ]); expect(exitCode).toEqual(0); expect( @@ -20,7 +26,11 @@ describe('"bonjour" CLI option', () => { }); it('should work using "--no-bonjour"', async () => { - const { exitCode, stderr } = await testBin(['--no-bonjour']); + const { exitCode, stderr } = await testBin([ + '--no-bonjour', + '--port', + port, + ]); expect(exitCode).toEqual(0); expect(normalizeStderr(stderr, { ipv6: true })).toMatchSnapshot(); diff --git a/test/cli/client-option.test.js b/test/cli/client-option.test.js index f70dc58c24..87e079e618 100644 --- a/test/cli/client-option.test.js +++ b/test/cli/client-option.test.js @@ -1,52 +1,79 @@ 'use strict'; const { testBin } = require('../helpers/test-bin'); +const port = require('../ports-map')['cli-client']; describe('"client" CLI option', () => { it('should work using "--client-transport sockjs"', async () => { - const { exitCode } = await testBin(['--client-transport', 'sockjs']); + const { exitCode } = await testBin([ + '--client-transport', + 'sockjs', + '--port', + port, + ]); expect(exitCode).toEqual(0); }); it('should work using "--client-transport ws"', async () => { - const { exitCode } = await testBin(['--client-transport', 'ws']); + const { exitCode } = await testBin([ + '--client-transport', + 'ws', + '--port', + port, + ]); expect(exitCode).toEqual(0); }); it('should work using "--client-overlay"', async () => { - const { exitCode } = await testBin(['--client-overlay']); + const { exitCode } = await testBin(['--client-overlay', '--port', port]); expect(exitCode).toEqual(0); }); it('should work using "--no-client-overlay"', async () => { - const { exitCode } = await testBin(['--no-client-overlay']); + const { exitCode } = await testBin(['--no-client-overlay', '--port', port]); expect(exitCode).toEqual(0); }); it('should work using "--client-overlay-errors"', async () => { - const { exitCode } = await testBin(['--client-overlay-errors']); + const { exitCode } = await testBin([ + '--client-overlay-errors', + '--port', + port, + ]); expect(exitCode).toEqual(0); }); it('should work using "--no-client-overlay-errors"', async () => { - const { exitCode } = await testBin(['--no-client-overlay-errors']); + const { exitCode } = await testBin([ + '--no-client-overlay-errors', + '--port', + port, + ]); expect(exitCode).toEqual(0); }); it('should work using "--client-overlay-warnings"', async () => { - const { exitCode } = await testBin(['--client-overlay-warnings']); + const { exitCode } = await testBin([ + '--client-overlay-warnings', + '--port', + port, + ]); expect(exitCode).toEqual(0); }); it('should work using "--no-client-overlay-warnings"', async () => { - const { exitCode } = await testBin(['--no-client-overlay-warnings']); + const { exitCode } = await testBin([ + '--no-client-overlay-warnings', + '--port', + port, + ]); expect(exitCode).toEqual(0); }); @@ -55,6 +82,8 @@ describe('"client" CLI option', () => { const { exitCode, stdout } = await testBin([ '--client-need-client-entry', '--stats=detailed', + '--port', + port, ]); expect(exitCode).toEqual(0); @@ -65,6 +94,8 @@ describe('"client" CLI option', () => { const { exitCode, stdout } = await testBin([ '--no-client-need-client-entry', '--stats=detailed', + '--port', + port, ]); expect(exitCode).toEqual(0); @@ -72,19 +103,28 @@ describe('"client" CLI option', () => { }); it('should work using "--client-logging"', async () => { - const { exitCode } = await testBin(['--client-logging', 'verbose']); + const { exitCode } = await testBin([ + '--client-logging', + 'verbose', + '--port', + port, + ]); expect(exitCode).toEqual(0); }); it('should work using "--client-progress"', async () => { - const { exitCode } = await testBin(['--client-progress']); + const { exitCode } = await testBin(['--client-progress', '--port', port]); expect(exitCode).toEqual(0); }); it('should work using "--no-client-progress"', async () => { - const { exitCode } = await testBin(['--no-client-progress']); + const { exitCode } = await testBin([ + '--no-client-progress', + '--port', + port, + ]); expect(exitCode).toEqual(0); }); @@ -93,6 +133,8 @@ describe('"client" CLI option', () => { const { exitCode, stdout } = await testBin([ '--client-hot-entry', '--stats=detailed', + '--port', + port, ]); expect(exitCode).toEqual(0); @@ -103,6 +145,8 @@ describe('"client" CLI option', () => { const { exitCode, stdout } = await testBin([ '--no-client-hot-entry', '--stats=detailed', + '--port', + port, ]); expect(exitCode).toEqual(0); @@ -114,6 +158,8 @@ describe('"client" CLI option', () => { '--client-hot-entry', '--no-hot', '--stats=detailed', + '--port', + port, ]); expect(exitCode).toEqual(0); @@ -125,6 +171,8 @@ describe('"client" CLI option', () => { '--no-client-hot-entry', '--hot', '--stats=detailed', + '--port', + port, ]); expect(exitCode).toEqual(0); @@ -135,6 +183,8 @@ describe('"client" CLI option', () => { const { exitCode } = await testBin([ '--client-web-socket-url', 'ws://myhost.com:8080/foo/test', + '--port', + port, ]); expect(exitCode).toEqual(0); @@ -144,6 +194,8 @@ describe('"client" CLI option', () => { const { exitCode } = await testBin([ '--client-web-socket-url-protocol', 'ws:', + '--port', + port, ]); expect(exitCode).toEqual(0); @@ -153,6 +205,8 @@ describe('"client" CLI option', () => { const { exitCode } = await testBin([ '--client-web-socket-url-hostname', '0.0.0.0', + '--port', + port, ]); expect(exitCode).toEqual(0); @@ -162,13 +216,20 @@ describe('"client" CLI option', () => { const { exitCode } = await testBin([ '--client-web-socket-url-pathname', '/ws', + '--port', + port, ]); expect(exitCode).toEqual(0); }); it('should work using "--client-web-socket-url-port"', async () => { - const { exitCode } = await testBin(['--client-web-socket-url-port', 8080]); + const { exitCode } = await testBin([ + '--client-web-socket-url-port', + 8080, + '--port', + port, + ]); expect(exitCode).toEqual(0); }); diff --git a/test/cli/colors.test.js b/test/cli/colors.test.js index c9053c503d..2467f65e1f 100644 --- a/test/cli/colors.test.js +++ b/test/cli/colors.test.js @@ -1,6 +1,7 @@ 'use strict'; const { testBin, normalizeStderr } = require('../helpers/test-bin'); +const port = require('../ports-map')['cli-colors']; const colorsDefaultStats = require.resolve( '../fixtures/cli-colors-default-stats/webpack.config' @@ -16,7 +17,9 @@ describe('colors', () => { it('should work use colors by default', async () => { const { exitCode, stderr, stdout } = await testBin( '--color', - colorsDefaultStats + colorsDefaultStats, + '--port', + port ); expect(exitCode).toEqual(0); @@ -25,7 +28,11 @@ describe('colors', () => { }); it('should work use colors using "--color"', async () => { - const { exitCode, stderr, stdout } = await testBin('--color'); + const { exitCode, stderr, stdout } = await testBin([ + '--color', + '--port', + port, + ]); expect(exitCode).toEqual(0); expect(normalizeStderr(stderr, { ipv6: true })).toMatchSnapshot('stderr'); @@ -33,7 +40,11 @@ describe('colors', () => { }); it('should work do not use colors using "--no-color"', async () => { - const { exitCode, stderr, stdout } = await testBin('--no-color'); + const { exitCode, stderr, stdout } = await testBin([ + '--no-color', + '--port', + port, + ]); expect(exitCode).toEqual(0); expect(normalizeStderr(stderr, { ipv6: true })).toMatchSnapshot('stderr'); @@ -41,7 +52,10 @@ describe('colors', () => { }); it('should work use colors using configuration with enabled colors', async () => { - const { exitCode, stderr, stdout } = await testBin('', colorsEnabled); + const { exitCode, stderr, stdout } = await testBin( + ['--port', port], + colorsEnabled + ); expect(exitCode).toEqual(0); expect(normalizeStderr(stderr, { ipv6: true })).toMatchSnapshot('stderr'); @@ -49,7 +63,10 @@ describe('colors', () => { }); it('should work and do not use colors using configuration with disabled colors', async () => { - const { exitCode, stderr, stdout } = await testBin('', colorsDisabled); + const { exitCode, stderr, stdout } = await testBin( + ['--port', port], + colorsDisabled + ); expect(exitCode).toEqual(0); expect(normalizeStderr(stderr, { ipv6: true })).toMatchSnapshot('stderr'); diff --git a/test/cli/compress-option.test.js b/test/cli/compress-option.test.js index d0fecfb621..616bdd9141 100644 --- a/test/cli/compress-option.test.js +++ b/test/cli/compress-option.test.js @@ -1,16 +1,17 @@ 'use strict'; const { testBin } = require('../helpers/test-bin'); +const port = require('../ports-map')['cli-compress']; describe('"compress" CLI option', () => { it('should work using "--compress"', async () => { - const { exitCode } = await testBin('--compress'); + const { exitCode } = await testBin(['--compress', '--port', port]); expect(exitCode).toEqual(0); }); it('should work using "--no-compress"', async () => { - const { exitCode } = await testBin('--no-compress'); + const { exitCode } = await testBin(['--no-compress', '--port', port]); expect(exitCode).toEqual(0); }); diff --git a/test/cli/historyApiFallback-option.test.js b/test/cli/historyApiFallback-option.test.js index 18b1108ded..210e062fba 100644 --- a/test/cli/historyApiFallback-option.test.js +++ b/test/cli/historyApiFallback-option.test.js @@ -1,17 +1,26 @@ 'use strict'; const { testBin, normalizeStderr } = require('../helpers/test-bin'); +const port = require('../ports-map')['cli-history-api-fallback']; describe('"historyApiFallback" CLI option', () => { it('should work using "--history-api-fallback"', async () => { - const { exitCode, stderr } = await testBin(['--history-api-fallback']); + const { exitCode, stderr } = await testBin([ + '--history-api-fallback', + '--port', + port, + ]); expect(exitCode).toEqual(0); expect(normalizeStderr(stderr, { ipv6: true })).toMatchSnapshot(); }); it('should work using "--no-history-api-fallback"', async () => { - const { exitCode, stderr } = await testBin(['--no-history-api-fallback']); + const { exitCode, stderr } = await testBin([ + '--no-history-api-fallback', + '--port', + port, + ]); expect(exitCode).toEqual(0); expect(normalizeStderr(stderr, { ipv6: true })).toMatchSnapshot(); diff --git a/test/cli/host-option.test.js b/test/cli/host-option.test.js index 7071128dc5..234121820c 100644 --- a/test/cli/host-option.test.js +++ b/test/cli/host-option.test.js @@ -2,41 +2,67 @@ const internalIp = require('internal-ip'); const { testBin, normalizeStderr } = require('../helpers/test-bin'); +const port = require('../ports-map')['cli-host']; const localIPv4 = internalIp.v4.sync(); const localIPv6 = internalIp.v6.sync(); describe('"host" CLI option', () => { it('should work using "--host 0.0.0.0" (IPv4)', async () => { - const { exitCode, stderr } = await testBin(['--host', '0.0.0.0']); + const { exitCode, stderr } = await testBin([ + '--host', + '0.0.0.0', + '--port', + port, + ]); expect(exitCode).toEqual(0); expect(normalizeStderr(stderr, { ipv6: true })).toMatchSnapshot('stderr'); }); it('should work using "--host ::" (IPv6)', async () => { - const { exitCode, stderr } = await testBin(['--host', '::']); + const { exitCode, stderr } = await testBin([ + '--host', + '::', + '--port', + port, + ]); expect(exitCode).toEqual(0); expect(normalizeStderr(stderr, { ipv6: true })).toMatchSnapshot('stderr'); }); it('should work using "--host ::1" (IPv6)', async () => { - const { exitCode, stderr } = await testBin(['--host', '::1']); + const { exitCode, stderr } = await testBin([ + '--host', + '::1', + '--port', + port, + ]); expect(exitCode).toEqual(0); expect(normalizeStderr(stderr)).toMatchSnapshot('stderr'); }); it('should work using "--host localhost"', async () => { - const { exitCode, stderr } = await testBin(['--host', 'localhost']); + const { exitCode, stderr } = await testBin([ + '--host', + 'localhost', + '--port', + port, + ]); expect(exitCode).toEqual(0); expect(normalizeStderr(stderr)).toMatchSnapshot('stderr'); }); it('should work using "--host 127.0.0.1" (IPv4)', async () => { - const { exitCode, stderr } = await testBin(['--host', '127.0.0.1']); + const { exitCode, stderr } = await testBin([ + '--host', + '127.0.0.1', + '--port', + port, + ]); expect(exitCode).toEqual(0); expect(normalizeStderr(stderr)).toMatchSnapshot('stderr'); @@ -46,6 +72,8 @@ describe('"host" CLI option', () => { const { exitCode, stderr } = await testBin([ '--host', '0:0:0:0:0:FFFF:7F00:0001', + '--port', + port, ]); expect(exitCode).toEqual(0); @@ -53,28 +81,48 @@ describe('"host" CLI option', () => { }); it(`should work using "--host "`, async () => { - const { exitCode, stderr } = await testBin(['--host', localIPv4]); + const { exitCode, stderr } = await testBin([ + '--host', + localIPv4, + '--port', + port, + ]); expect(exitCode).toEqual(0); expect(normalizeStderr(stderr)).toMatchSnapshot('stderr'); }); it.skip(`should work using "--host "`, async () => { - const { exitCode, stderr } = await testBin(['--host', localIPv6]); + const { exitCode, stderr } = await testBin([ + '--host', + localIPv6, + '--port', + port, + ]); expect(exitCode).toEqual(0); expect(normalizeStderr(stderr)).toMatchSnapshot('stderr'); }); it('should work using "--host local-ip"', async () => { - const { exitCode, stderr } = await testBin(['--host', 'local-ip']); + const { exitCode, stderr } = await testBin([ + '--host', + 'local-ip', + '--port', + port, + ]); expect(exitCode).toEqual(0); expect(normalizeStderr(stderr)).toMatchSnapshot('stderr'); }); it('should work using "--host local-ipv4"', async () => { - const { exitCode, stderr } = await testBin(['--host', 'local-ipv4']); + const { exitCode, stderr } = await testBin([ + '--host', + 'local-ipv4', + '--port', + port, + ]); expect(exitCode).toEqual(0); expect(normalizeStderr(stderr)).toMatchSnapshot('stderr'); diff --git a/test/cli/hot-option.test.js b/test/cli/hot-option.test.js index 9ad498c197..f26efef1c9 100644 --- a/test/cli/hot-option.test.js +++ b/test/cli/hot-option.test.js @@ -1,10 +1,16 @@ 'use strict'; const { testBin } = require('../helpers/test-bin'); +const port = require('../ports-map')['cli-hot']; describe('"hot" CLI option', () => { it('should work using "--hot"', async () => { - const { exitCode, stdout } = await testBin(['--hot', '--stats=detailed']); + const { exitCode, stdout } = await testBin([ + '--hot', + '--stats=detailed', + '--port', + port, + ]); expect(exitCode).toEqual(0); expect(stdout).toContain('webpack/hot/dev-server.js'); @@ -14,6 +20,8 @@ describe('"hot" CLI option', () => { const { exitCode, stdout } = await testBin([ '--no-hot', '--stats=detailed', + '--port', + port, ]); expect(exitCode).toEqual(0); @@ -21,7 +29,12 @@ describe('"hot" CLI option', () => { }); it('should work using "--hot only"', async () => { - const { exitCode, stdout } = await testBin(['--hot', 'only']); + const { exitCode, stdout } = await testBin([ + '--hot', + 'only', + '--port', + port, + ]); expect(exitCode).toEqual(0); expect(stdout).toContain('/hot/only-dev-server.js'); diff --git a/test/cli/http2-option.test.js b/test/cli/http2-option.test.js index 4738cdee3a..a9caab6f89 100644 --- a/test/cli/http2-option.test.js +++ b/test/cli/http2-option.test.js @@ -1,10 +1,11 @@ 'use strict'; const { testBin, normalizeStderr } = require('../helpers/test-bin'); +const port = require('../ports-map')['cli-http2']; describe('"http2" CLI option', () => { it('should work using "--http2"', async () => { - const { exitCode, stderr } = await testBin(['--http2']); + const { exitCode, stderr } = await testBin(['--http2', '--port', port]); expect(exitCode).toEqual(0); expect( @@ -13,7 +14,7 @@ describe('"http2" CLI option', () => { }); it('should work using "--no-http2"', async () => { - const { exitCode, stderr } = await testBin(['--no-http2']); + const { exitCode, stderr } = await testBin(['--no-http2', '--port', port]); expect(exitCode).toEqual(0); expect(normalizeStderr(stderr, { ipv6: true })).toMatchSnapshot(); diff --git a/test/cli/https-option.test.js b/test/cli/https-option.test.js index 40f43b8e7b..9c50e48f69 100644 --- a/test/cli/https-option.test.js +++ b/test/cli/https-option.test.js @@ -2,6 +2,7 @@ const path = require('path'); const { testBin, normalizeStderr } = require('../helpers/test-bin'); +const port = require('../ports-map')['cli-https']; const httpsCertificateDirectory = path.resolve( __dirname, @@ -10,7 +11,7 @@ const httpsCertificateDirectory = path.resolve( describe('"https" CLI option', () => { it('should work using "--https"', async () => { - const { exitCode, stderr } = await testBin(['--https']); + const { exitCode, stderr } = await testBin(['--https', '--port', port]); expect(exitCode).toEqual(0); expect( @@ -42,9 +43,18 @@ describe('"https" CLI option', () => { const cert = path.join(httpsCertificateDirectory, 'server.crt'); const passphrase = 'webpack-dev-server'; - const { exitCode, stderr } = await testBin( - `--https-key ${key} --https-pfx ${pfxFile} --https-passphrase ${passphrase} --https-cert ${cert}` - ); + const { exitCode, stderr } = await testBin([ + '--https-key', + key, + '--https-pfx', + pfxFile, + '--https-passphrase', + passphrase, + '--https-cert', + cert, + '--port', + port, + ]); expect(exitCode).toEqual(0); expect( @@ -53,7 +63,11 @@ describe('"https" CLI option', () => { }); it('should work using "--https-request-cert"', async () => { - const { exitCode, stderr } = await testBin(['--https-request-cert']); + const { exitCode, stderr } = await testBin([ + '--https-request-cert', + '--port', + port, + ]); expect(exitCode).toEqual(0); expect( @@ -62,7 +76,11 @@ describe('"https" CLI option', () => { }); it('should work using "--no-https-request-cert"', async () => { - const { exitCode, stderr } = await testBin(['--no-https-request-cert']); + const { exitCode, stderr } = await testBin([ + '--no-https-request-cert', + '--port', + port, + ]); expect(exitCode).toEqual(0); expect( @@ -71,7 +89,7 @@ describe('"https" CLI option', () => { }); it('should work using "--no-https"', async () => { - const { exitCode, stderr } = await testBin(['--no-https']); + const { exitCode, stderr } = await testBin(['--no-https', '--port', port]); expect(exitCode).toEqual(0); expect(normalizeStderr(stderr, { ipv6: true })).toMatchSnapshot(); diff --git a/test/cli/ipc-option.test.js b/test/cli/ipc-option.test.js new file mode 100644 index 0000000000..fdb5cd14cb --- /dev/null +++ b/test/cli/ipc-option.test.js @@ -0,0 +1,26 @@ +'use strict'; + +const path = require('path'); +const os = require('os'); +const { testBin, normalizeStderr } = require('../helpers/test-bin'); + +describe('"ipc" CLI option', () => { + it('should work using "--ipc"', async () => { + const { exitCode, stderr } = await testBin(['--ipc']); + + expect(exitCode).toEqual(0); + expect(normalizeStderr(stderr)).toMatchSnapshot('stderr'); + }); + + it('should work using "--ipc="', async () => { + const isWindows = process.platform === 'win32'; + const pipePrefix = isWindows ? '\\\\.\\pipe\\' : os.tmpdir(); + const pipeName = `webpack-dev-server.cli.sock`; + const ipc = path.join(pipePrefix, pipeName); + + const { exitCode, stderr } = await testBin(['--ipc', ipc]); + + expect(exitCode).toEqual(0); + expect(normalizeStderr(stderr)).toMatchSnapshot('stderr'); + }); +}); diff --git a/test/cli/liveReload-option.test.js b/test/cli/liveReload-option.test.js index 8d9980f92c..ca59cb29b3 100644 --- a/test/cli/liveReload-option.test.js +++ b/test/cli/liveReload-option.test.js @@ -1,16 +1,17 @@ 'use strict'; const { testBin } = require('../helpers/test-bin'); +const port = require('../ports-map')['cli-live-reload']; describe('"liveReload" CLI option', () => { it('should work using "--live-reload"', async () => { - const { exitCode } = await testBin(['--live-reload']); + const { exitCode } = await testBin(['--live-reload', '--port', port]); expect(exitCode).toEqual(0); }); it('should work using "--no-live-reload"', async () => { - const { exitCode } = await testBin(['--no-live-reload']); + const { exitCode } = await testBin(['--no-live-reload', '--port', port]); expect(exitCode).toEqual(0); }); diff --git a/test/cli/open-option.test.js b/test/cli/open-option.test.js index 3152741189..395bbaf0c7 100644 --- a/test/cli/open-option.test.js +++ b/test/cli/open-option.test.js @@ -1,124 +1,197 @@ 'use strict'; const { testBin } = require('../helpers/test-bin'); +const port = require('../ports-map')['cli-open']; describe('"open" CLI option', () => { it('should work using "--open"', async () => { - const { exitCode } = await testBin(['--open']); + const { exitCode } = await testBin(['--open', '--port', port]); expect(exitCode).toEqual(0); }); it('should work using "--open /index.html"', async () => { - const { exitCode } = await testBin('--open /index.html'); + const { exitCode } = await testBin([ + '--open', + '/index.html', + '--port', + port, + ]); expect(exitCode).toEqual(0); }); it('should work using "--open /first.html second.html"', async () => { - const { exitCode } = await testBin('--open /first.html second.html'); + const { exitCode } = await testBin([ + '--open', + '/first.html', + 'second.html', + '--port', + port, + ]); expect(exitCode).toEqual(0); }); it('should work using "--no-open"', async () => { - const { exitCode } = await testBin('--no-open'); + const { exitCode } = await testBin(['--no-open', '--port', port]); expect(exitCode).toEqual(0); }); it('should work using "--open-reset"', async () => { - const { exitCode } = await testBin('--open-reset --open /third.html'); + const { exitCode } = await testBin([ + '--open-reset', + '--open', + '/third.html', + '--port', + port, + ]); expect(exitCode).toEqual(0); }); it('should work using "--open-reset --open-target"', async () => { - const { exitCode } = await testBin('--open-reset --open-target'); + const { exitCode } = await testBin([ + '--open-reset', + '--open-target', + '--port', + port, + ]); expect(exitCode).toEqual(0); }); it('should work using "--open-reset --open-target /third.html"', async () => { - const { exitCode } = await testBin( - '--open-reset --open-target /third.html' - ); + const { exitCode } = await testBin([ + '--open-reset', + '--open-target', + '/third.html', + '--port', + port, + ]); expect(exitCode).toEqual(0); }); it('should work using "--open-app google-chrome"', async () => { - const { exitCode } = await testBin('--open-app google-chrome'); + const { exitCode } = await testBin([ + '--open-app', + 'google-chrome', + '--port', + port, + ]); expect(exitCode).toEqual(0); }); it('should work using "--open-app-name google-chrome"', async () => { - const { exitCode } = await testBin('--open-app-name google-chrome'); + const { exitCode } = await testBin([ + '--open-app-name', + 'google-chrome', + '--port', + port, + ]); expect(exitCode).toEqual(0); }); it('should work using "--open-app-name-reset --open-app-name firefox"', async () => { - const { exitCode } = await testBin( - '-open-app-name-reset --open-app-name firefox' - ); + const { exitCode } = await testBin([ + '--open-app-name-reset', + '--open-app-name', + 'firefox', + '--port', + port, + ]); expect(exitCode).toEqual(0); }); it('should work using "--open-target"', async () => { - const { exitCode } = await testBin('-open-target'); + const { exitCode } = await testBin(['-open-target', '--port', port]); expect(exitCode).toEqual(0); }); it('should work using "--no-open-target"', async () => { - const { exitCode } = await testBin('--no-open-target'); + const { exitCode } = await testBin(['--no-open-target', '--port', port]); expect(exitCode).toEqual(0); }); it('should work using "--open-target index.html"', async () => { - const { exitCode } = await testBin('--open-target index.html'); + const { exitCode } = await testBin([ + '--open-target', + 'index.html', + '--port', + port, + ]); expect(exitCode).toEqual(0); }); it('should work using "--open-target-reset"', async () => { - const { exitCode } = await testBin( - '--open-target-reset --open-target first.html' - ); + const { exitCode } = await testBin([ + '--open-target-reset', + '--open-target', + 'first.html', + '--port', + port, + ]); expect(exitCode).toEqual(0); }); it('should work using "--open-target /first.html second.html"', async () => { - const { exitCode } = await testBin('--open-target /first.html second.html'); + const { exitCode } = await testBin([ + '--open-target', + '/first.html', + 'second.html', + '--port', + port, + ]); expect(exitCode).toEqual(0); }); it('should work using "--open-target /index.html --open-app google-chrome"', async () => { - const { exitCode } = await testBin( - '--open-target /index.html --open-app google-chrome' - ); + const { exitCode } = await testBin([ + '--open-target', + '/index.html', + '--open-app', + 'google-chrome', + '--port', + port, + ]); expect(exitCode).toEqual(0); }); it('should work using "--open-target /index.html --open-app-name google-chrome"', async () => { - const { exitCode } = await testBin( - '--open-target /index.html --open-app-name google-chrome' - ); + const { exitCode } = await testBin([ + '--open-target', + '/index.html', + '--open-app-name', + 'google-chrome', + '--port', + port, + ]); expect(exitCode).toEqual(0); }); it('should work using "--open-target /index.html --open-app google-chrome --open-app-name google-chrome"', async () => { - const { exitCode } = await testBin( - '--open-target /index.html --open-app google-chrome --open-app-name google-chrome' - ); + const { exitCode } = await testBin([ + '--open-target', + '/index.html', + '--open-app', + 'google-chrome', + '--open-app-name', + 'google-chrome', + '--port', + port, + ]); expect(exitCode).toEqual(0); }); diff --git a/test/cli/static-option.test.js b/test/cli/static-option.test.js index 84d4bd7be3..5d84591931 100644 --- a/test/cli/static-option.test.js +++ b/test/cli/static-option.test.js @@ -1,95 +1,144 @@ 'use strict'; const { testBin, normalizeStderr } = require('../helpers/test-bin'); +const port = require('../ports-map')['cli-static']; describe('"static" CLI option', () => { it('should work using "--static"', async () => { - const { exitCode, stderr } = await testBin('--static'); + const { exitCode, stderr } = await testBin(['--static', '--port', port]); expect(exitCode).toEqual(0); expect(normalizeStderr(stderr, { ipv6: true })).toMatchSnapshot('stderr'); }); it('should work using "--static new-static"', async () => { - const { exitCode, stderr } = await testBin('--static new-static'); + const { exitCode, stderr } = await testBin([ + '--static', + 'new-static', + '--port', + port, + ]); expect(exitCode).toEqual(0); expect(normalizeStderr(stderr, { ipv6: true })).toMatchSnapshot('stderr'); }); it('should work using "--static new-static --static other-static"', async () => { - const { exitCode, stderr } = await testBin( - '--static new-static --static other-static' - ); + const { exitCode, stderr } = await testBin([ + '--static', + 'new-static', + '--static', + 'other-static', + '--port', + port, + ]); expect(exitCode).toEqual(0); expect(normalizeStderr(stderr, { ipv6: true })).toMatchSnapshot('stderr'); }); it('should work using "--static-reset"', async () => { - const { exitCode, stderr } = await testBin( - '--static-reset --static new-static-after-reset' - ); + const { exitCode, stderr } = await testBin([ + '--static-reset', + '--static', + 'new-static-after-reset', + '--port', + port, + ]); expect(exitCode).toEqual(0); expect(normalizeStderr(stderr, { ipv6: true })).toMatchSnapshot('stderr'); }); it('should work using "--static-reset --static-directory new-static-directory"', async () => { - const { exitCode, stderr } = await testBin( - '--static-reset --static-directory new-static-directory' - ); + const { exitCode, stderr } = await testBin([ + '--static-reset', + '--static-directory', + 'new-static-directory', + '--port', + port, + ]); expect(exitCode).toEqual(0); expect(normalizeStderr(stderr, { ipv6: true })).toMatchSnapshot('stderr'); }); it('should work using "--static-directory static-dir"', async () => { - const { exitCode, stderr } = await testBin('--static-directory static-dir'); + const { exitCode, stderr } = await testBin([ + '--static-directory', + 'static-dir', + '--port', + port, + ]); expect(exitCode).toEqual(0); expect(normalizeStderr(stderr, { ipv6: true })).toMatchSnapshot('stderr'); }); it('should work using "--static-public-path /public"', async () => { - const { exitCode, stderr } = await testBin('--static-public-path /public'); + const { exitCode, stderr } = await testBin([ + '--static-public-path', + '/public', + '--port', + port, + ]); expect(exitCode).toEqual(0); expect(normalizeStderr(stderr, { ipv6: true })).toMatchSnapshot('stderr'); }); it('should work using "--static-public-path-reset"', async () => { - const { exitCode, stderr } = await testBin( - '--static-public-path-reset --static-public-path /new-public' - ); + const { exitCode, stderr } = await testBin([ + '--static-public-path-reset', + '--static-public-path', + '/new-public', + '--port', + port, + ]); expect(exitCode).toEqual(0); expect(normalizeStderr(stderr, { ipv6: true })).toMatchSnapshot('stderr'); }); it('should work using "--static-serve-index"', async () => { - const { exitCode, stderr } = await testBin('--static-serve-index'); + const { exitCode, stderr } = await testBin([ + '--static-serve-index', + '--port', + port, + ]); expect(exitCode).toEqual(0); expect(normalizeStderr(stderr, { ipv6: true })).toMatchSnapshot('stderr'); }); it('should work using "--no-static-serve-index"', async () => { - const { exitCode, stderr } = await testBin('--no-static-serve-index'); + const { exitCode, stderr } = await testBin([ + '--no-static-serve-index', + '--port', + port, + ]); expect(exitCode).toEqual(0); expect(normalizeStderr(stderr, { ipv6: true })).toMatchSnapshot('stderr'); }); it('should work using "--static-watch"', async () => { - const { exitCode, stderr } = await testBin('--static-watch'); + const { exitCode, stderr } = await testBin([ + '--static-watch', + '--port', + port, + ]); expect(exitCode).toEqual(0); expect(normalizeStderr(stderr, { ipv6: true })).toMatchSnapshot('stderr'); }); it('should work using "--no-static-watch"', async () => { - const { exitCode, stderr } = await testBin('--no-static-watch'); + const { exitCode, stderr } = await testBin([ + '--no-static-watch', + '--port', + port, + ]); expect(exitCode).toEqual(0); expect(normalizeStderr(stderr, { ipv6: true })).toMatchSnapshot('stderr'); diff --git a/test/cli/watchFiles-option.test.js b/test/cli/watchFiles-option.test.js index 3d76b6d3ef..efc9826060 100644 --- a/test/cli/watchFiles-option.test.js +++ b/test/cli/watchFiles-option.test.js @@ -2,6 +2,7 @@ const path = require('path'); const { testBin, normalizeStderr } = require('../helpers/test-bin'); +const port = require('../ports-map')['cli-watch-files']; describe('"watchFiles" CLI option', () => { it('should work using "--watch-files "', async () => { @@ -10,6 +11,8 @@ describe('"watchFiles" CLI option', () => { const { exitCode, stderr } = await testBin([ '--watch-files', watchDirectory, + '--port', + port, ]); expect(exitCode).toEqual(0); @@ -28,6 +31,8 @@ describe('"watchFiles" CLI option', () => { watchDirectory, '--watch-files', watchOtherDirectory, + '--port', + port, ]); expect(exitCode).toEqual(0); @@ -41,6 +46,8 @@ describe('"watchFiles" CLI option', () => { '--watch-files-reset', '--watch-files', watchDirectory, + '--port', + port, ]); expect(exitCode).toEqual(0); diff --git a/test/cli/webSocketServer-option.test.js b/test/cli/webSocketServer-option.test.js index cdba401893..2cc3ad21fd 100644 --- a/test/cli/webSocketServer-option.test.js +++ b/test/cli/webSocketServer-option.test.js @@ -1,16 +1,27 @@ 'use strict'; const { testBin } = require('../helpers/test-bin'); +const port = require('../ports-map')['cli-web-socket-server']; describe('"webSocketServer" CLI option', () => { it('should work using "--web-socket-server sockjs"', async () => { - const { exitCode } = await testBin(['--web-socket-server', 'sockjs']); + const { exitCode } = await testBin([ + '--web-socket-server', + 'sockjs', + '--port', + port, + ]); expect(exitCode).toEqual(0); }); it('should work using "--web-socket-server ws"', async () => { - const { exitCode } = await testBin(['--web-socket-server', 'ws']); + const { exitCode } = await testBin([ + '--web-socket-server', + 'ws', + '--port', + port, + ]); expect(exitCode).toEqual(0); }); diff --git a/test/e2e/__snapshots__/ipc.test.js.snap.webpack4 b/test/e2e/__snapshots__/ipc.test.js.snap.webpack4 new file mode 100644 index 0000000000..e31bdaa38e --- /dev/null +++ b/test/e2e/__snapshots__/ipc.test.js.snap.webpack4 @@ -0,0 +1,45 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`web socket server URL should work with the "ipc" option using "string" value ("sockjs"): console messages 1`] = ` +Array [ + "[HMR] Waiting for update signal from WDS...", + "Hey.", + "[webpack-dev-server] Hot Module Replacement enabled.", + "[webpack-dev-server] Live Reloading enabled.", +] +`; + +exports[`web socket server URL should work with the "ipc" option using "string" value ("sockjs"): page errors 1`] = `Array []`; + +exports[`web socket server URL should work with the "ipc" option using "string" value ("ws"): console messages 1`] = ` +Array [ + "[HMR] Waiting for update signal from WDS...", + "Hey.", + "[webpack-dev-server] Hot Module Replacement enabled.", + "[webpack-dev-server] Live Reloading enabled.", +] +`; + +exports[`web socket server URL should work with the "ipc" option using "string" value ("ws"): page errors 1`] = `Array []`; + +exports[`web socket server URL should work with the "ipc" option using "true" value ("sockjs"): console messages 1`] = ` +Array [ + "[HMR] Waiting for update signal from WDS...", + "Hey.", + "[webpack-dev-server] Hot Module Replacement enabled.", + "[webpack-dev-server] Live Reloading enabled.", +] +`; + +exports[`web socket server URL should work with the "ipc" option using "true" value ("sockjs"): page errors 1`] = `Array []`; + +exports[`web socket server URL should work with the "ipc" option using "true" value ("ws"): console messages 1`] = ` +Array [ + "[HMR] Waiting for update signal from WDS...", + "Hey.", + "[webpack-dev-server] Hot Module Replacement enabled.", + "[webpack-dev-server] Live Reloading enabled.", +] +`; + +exports[`web socket server URL should work with the "ipc" option using "true" value ("ws"): page errors 1`] = `Array []`; diff --git a/test/e2e/__snapshots__/ipc.test.js.snap.webpack5 b/test/e2e/__snapshots__/ipc.test.js.snap.webpack5 new file mode 100644 index 0000000000..e31bdaa38e --- /dev/null +++ b/test/e2e/__snapshots__/ipc.test.js.snap.webpack5 @@ -0,0 +1,45 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`web socket server URL should work with the "ipc" option using "string" value ("sockjs"): console messages 1`] = ` +Array [ + "[HMR] Waiting for update signal from WDS...", + "Hey.", + "[webpack-dev-server] Hot Module Replacement enabled.", + "[webpack-dev-server] Live Reloading enabled.", +] +`; + +exports[`web socket server URL should work with the "ipc" option using "string" value ("sockjs"): page errors 1`] = `Array []`; + +exports[`web socket server URL should work with the "ipc" option using "string" value ("ws"): console messages 1`] = ` +Array [ + "[HMR] Waiting for update signal from WDS...", + "Hey.", + "[webpack-dev-server] Hot Module Replacement enabled.", + "[webpack-dev-server] Live Reloading enabled.", +] +`; + +exports[`web socket server URL should work with the "ipc" option using "string" value ("ws"): page errors 1`] = `Array []`; + +exports[`web socket server URL should work with the "ipc" option using "true" value ("sockjs"): console messages 1`] = ` +Array [ + "[HMR] Waiting for update signal from WDS...", + "Hey.", + "[webpack-dev-server] Hot Module Replacement enabled.", + "[webpack-dev-server] Live Reloading enabled.", +] +`; + +exports[`web socket server URL should work with the "ipc" option using "true" value ("sockjs"): page errors 1`] = `Array []`; + +exports[`web socket server URL should work with the "ipc" option using "true" value ("ws"): console messages 1`] = ` +Array [ + "[HMR] Waiting for update signal from WDS...", + "Hey.", + "[webpack-dev-server] Hot Module Replacement enabled.", + "[webpack-dev-server] Live Reloading enabled.", +] +`; + +exports[`web socket server URL should work with the "ipc" option using "true" value ("ws"): page errors 1`] = `Array []`; diff --git a/test/e2e/ipc.test.js b/test/e2e/ipc.test.js new file mode 100644 index 0000000000..d0f48c69d7 --- /dev/null +++ b/test/e2e/ipc.test.js @@ -0,0 +1,387 @@ +'use strict'; + +const os = require('os'); +const net = require('net'); +const path = require('path'); +const http = require('http'); +const webpack = require('webpack'); +const httpProxy = require('http-proxy'); +const Server = require('../../lib/Server'); +const config = require('../fixtures/client-config/webpack.config'); +const runBrowser = require('../helpers/run-browser'); +const port1 = require('../ports-map').ipc; + +const webSocketServers = ['ws', 'sockjs']; + +describe('web socket server URL', () => { + for (const webSocketServer of webSocketServers) { + const websocketURLProtocol = webSocketServer === 'ws' ? 'ws' : 'http'; + + it(`should work with the "ipc" option using "true" value ("${webSocketServer}")`, async () => { + const devServerHost = '127.0.0.1'; + const proxyHost = devServerHost; + const proxyPort = port1; + + const compiler = webpack(config); + const devServerOptions = { + webSocketServer, + host: devServerHost, + ipc: true, + }; + const server = new Server(devServerOptions, compiler); + + // Avoid racing between CLI test and this test + server.options.ipc = server.options.ipc.replace( + /webpack-dev-server/, + `webpack-dev-server.${process.pid}-0` + ); + + await new Promise((resolve, reject) => { + server.listen((error) => { + if (error) { + reject(error); + + return; + } + + resolve(); + }); + }); + + function startProxy(callback) { + const proxy = httpProxy.createProxyServer({ + target: { socketPath: server.options.ipc }, + }); + + const proxyServer = http.createServer((request, response) => { + // You can define here your custom logic to handle the request + // and then proxy the request. + proxy.web(request, response); + }); + + proxyServer.on('upgrade', (request, socket, head) => { + proxy.ws(request, socket, head); + }); + + return proxyServer.listen(proxyPort, proxyHost, callback); + } + + const proxy = await new Promise((resolve) => { + const proxyCreated = startProxy(() => { + resolve(proxyCreated); + }); + }); + + const { page, browser } = await runBrowser(); + + const pageErrors = []; + const consoleMessages = []; + + page + .on('console', (message) => { + consoleMessages.push(message); + }) + .on('pageerror', (error) => { + pageErrors.push(error); + }); + + const webSocketRequests = []; + + if (webSocketServer === 'ws') { + const client = page._client; + + client.on('Network.webSocketCreated', (test) => { + webSocketRequests.push(test); + }); + } else { + page.on('request', (request) => { + if (/\/ws\//.test(request.url())) { + webSocketRequests.push({ url: request.url() }); + } + }); + } + + await page.goto(`http://${proxyHost}:${proxyPort}/main`, { + waitUntil: 'networkidle0', + }); + + const webSocketRequest = webSocketRequests[0]; + + expect(webSocketRequest.url).toContain( + `${websocketURLProtocol}://${devServerHost}:${proxyPort}/ws` + ); + expect(consoleMessages.map((message) => message.text())).toMatchSnapshot( + 'console messages' + ); + expect(pageErrors).toMatchSnapshot('page errors'); + + proxy.close(); + + await browser.close(); + await new Promise((resolve, reject) => { + server.close((error) => { + if (error) { + reject(error); + + return; + } + + resolve(); + }); + }); + }); + + it(`should work with the "ipc" option using "string" value ("${webSocketServer}")`, async () => { + const isWindows = process.platform === 'win32'; + const pipePrefix = isWindows ? '\\\\.\\pipe\\' : os.tmpdir(); + const pipeName = `webpack-dev-server.${process.pid}-1.sock`; + const ipc = path.join(pipePrefix, pipeName); + + const devServerHost = '127.0.0.1'; + const proxyHost = devServerHost; + const proxyPort = port1; + + const compiler = webpack(config); + const devServerOptions = { + webSocketServer, + host: devServerHost, + ipc, + }; + const server = new Server(devServerOptions, compiler); + + await new Promise((resolve, reject) => { + server.listen((error) => { + if (error) { + reject(error); + + return; + } + + resolve(); + }); + }); + + function startProxy(callback) { + const proxy = httpProxy.createProxyServer({ + target: { socketPath: ipc }, + }); + + const proxyServer = http.createServer((request, response) => { + // You can define here your custom logic to handle the request + // and then proxy the request. + proxy.web(request, response); + }); + + proxyServer.on('upgrade', (request, socket, head) => { + proxy.ws(request, socket, head); + }); + + return proxyServer.listen(proxyPort, proxyHost, callback); + } + + const proxy = await new Promise((resolve) => { + const proxyCreated = startProxy(() => { + resolve(proxyCreated); + }); + }); + + const { page, browser } = await runBrowser(); + + const pageErrors = []; + const consoleMessages = []; + + page + .on('console', (message) => { + consoleMessages.push(message); + }) + .on('pageerror', (error) => { + pageErrors.push(error); + }); + + const webSocketRequests = []; + + if (webSocketServer === 'ws') { + const client = page._client; + + client.on('Network.webSocketCreated', (test) => { + webSocketRequests.push(test); + }); + } else { + page.on('request', (request) => { + if (/\/ws\//.test(request.url())) { + webSocketRequests.push({ url: request.url() }); + } + }); + } + + await page.goto(`http://${proxyHost}:${proxyPort}/main`, { + waitUntil: 'networkidle0', + }); + + const webSocketRequest = webSocketRequests[0]; + + expect(webSocketRequest.url).toContain( + `${websocketURLProtocol}://${devServerHost}:${proxyPort}/ws` + ); + expect(consoleMessages.map((message) => message.text())).toMatchSnapshot( + 'console messages' + ); + expect(pageErrors).toMatchSnapshot('page errors'); + + proxy.close(); + + await browser.close(); + await new Promise((resolve, reject) => { + server.close((error) => { + if (error) { + reject(error); + + return; + } + + resolve(); + }); + }); + }); + + // TODO un skip after implement new API + it.skip(`should work with the "ipc" option using "string" value and remove old ("${webSocketServer}")`, async () => { + const isWindows = process.platform === 'win32'; + const localRelative = path.relative(process.cwd(), `${os.tmpdir()}/`); + const pipePrefix = isWindows ? '\\\\.\\pipe\\' : localRelative; + const pipeName = `webpack-dev-server.${process.pid}-2.sock`; + const ipc = path.join(pipePrefix, pipeName); + + const ipcServer = await new Promise((resolve, reject) => { + const server = net.Server(); + + server.on('error', (error) => { + reject(error); + }); + + return server.listen(ipc, () => { + resolve(); + }); + }); + + const devServerHost = '127.0.0.1'; + const proxyHost = devServerHost; + const proxyPort = port1; + + const compiler = webpack(config); + const devServerOptions = { + webSocketServer, + host: devServerHost, + ipc, + }; + const server = new Server(devServerOptions, compiler); + + await new Promise((resolve, reject) => { + server.listen((error) => { + if (error) { + reject(error); + + return; + } + + resolve(); + }); + }); + + function startProxy(callback) { + const proxy = httpProxy.createProxyServer({ + target: { socketPath: ipc }, + }); + + const proxyServer = http.createServer((request, response) => { + // You can define here your custom logic to handle the request + // and then proxy the request. + proxy.web(request, response); + }); + + proxyServer.on('upgrade', (request, socket, head) => { + proxy.ws(request, socket, head); + }); + + return proxyServer.listen(proxyPort, proxyHost, callback); + } + + console.log('HERE'); + const proxy = await new Promise((resolve) => { + const proxyCreated = startProxy(() => { + resolve(proxyCreated); + }); + }); + + const { page, browser } = await runBrowser(); + + const pageErrors = []; + const consoleMessages = []; + + page + .on('console', (message) => { + consoleMessages.push(message); + }) + .on('pageerror', (error) => { + pageErrors.push(error); + }); + + const webSocketRequests = []; + + if (webSocketServer === 'ws') { + const client = page._client; + + client.on('Network.webSocketCreated', (test) => { + webSocketRequests.push(test); + }); + } else { + page.on('request', (request) => { + if (/\/ws\//.test(request.url())) { + webSocketRequests.push({ url: request.url() }); + } + }); + } + + console.log(`http://${proxyHost}:${proxyPort}/main`); + await page.goto(`http://${proxyHost}:${proxyPort}/main`, { + waitUntil: 'networkidle0', + }); + + const webSocketRequest = webSocketRequests[0]; + + expect(webSocketRequest.url).toContain( + `${websocketURLProtocol}://${devServerHost}:${proxyPort}/ws` + ); + expect(consoleMessages.map((message) => message.text())).toMatchSnapshot( + 'console messages' + ); + expect(pageErrors).toMatchSnapshot('page errors'); + + proxy.close(); + + await new Promise((resolve, reject) => { + ipcServer.close((error) => { + if (error) { + reject(error); + + return; + } + + resolve(); + }); + }); + await browser.close(); + await new Promise((resolve, reject) => { + server.close((error) => { + if (error) { + reject(error); + + return; + } + + resolve(); + }); + }); + }); + } +}); diff --git a/test/e2e/stats.test.js b/test/e2e/stats.test.js index 9ed57a3f37..e8be06111f 100644 --- a/test/e2e/stats.test.js +++ b/test/e2e/stats.test.js @@ -4,7 +4,7 @@ const webpack = require('webpack'); const Server = require('../../lib/Server'); const config = require('../fixtures/client-config/webpack.config'); const runBrowser = require('../helpers/run-browser'); -const port = require('../ports-map').logging; +const port = require('../ports-map').stats; global.console.log = jest.fn(); diff --git a/test/e2e/web-socket-communication.test.js b/test/e2e/web-socket-communication.test.js index b5de07748d..60f16c2c18 100644 --- a/test/e2e/web-socket-communication.test.js +++ b/test/e2e/web-socket-communication.test.js @@ -6,7 +6,7 @@ const Server = require('../../lib/Server'); const WebsocketServer = require('../../lib/servers/WebsocketServer'); const config = require('../fixtures/client-config/webpack.config'); const runBrowser = require('../helpers/run-browser'); -const port = require('../ports-map')['web-socket-heartbeat']; +const port = require('../ports-map')['web-socket-communication']; describe('web socket communication', () => { const webSocketServers = ['ws', 'sockjs']; diff --git a/test/e2e/web-socket-server-and-transport.test.js b/test/e2e/web-socket-server-and-transport.test.js index 6ca3e1135a..3f968bf7f9 100644 --- a/test/e2e/web-socket-server-and-transport.test.js +++ b/test/e2e/web-socket-server-and-transport.test.js @@ -7,7 +7,7 @@ const sockjsConfig = require('../fixtures/provide-plugin-sockjs-config/webpack.c const wsConfig = require('../fixtures/provide-plugin-ws-config/webpack.config'); const customConfig = require('../fixtures/provide-plugin-custom/webpack.config'); const runBrowser = require('../helpers/run-browser'); -const port = require('../ports-map')['web-socket-server-and-transport.test']; +const port = require('../ports-map')['web-socket-server-and-transport']; describe('web socket server and transport', () => { it('should use default transport ("ws")', async () => { diff --git a/test/helpers/test-bin.js b/test/helpers/test-bin.js index 078019cb73..73c32e7d7c 100644 --- a/test/helpers/test-bin.js +++ b/test/helpers/test-bin.js @@ -1,5 +1,6 @@ 'use strict'; +const os = require('os'); const path = require('path'); const execa = require('execa'); const stripAnsi = require('strip-ansi'); @@ -46,7 +47,9 @@ const normalizeStderr = (stderr, options = {}) => { normalizedStderr = normalizedStderr .replace(/\\/g, '/') - .replace(new RegExp(process.cwd().replace(/\\/g, '/'), 'g'), ''); + .replace(new RegExp(process.cwd().replace(/\\/g, '/'), 'g'), '') + .replace(new RegExp(os.tmpdir().replace(/\\/g, '/'), 'g'), '') + .replace(new RegExp('\\\\.\\pipe'.replace(/\\/g, '/'), 'g'), ''); const networkIPv4 = internalIp.v4.sync(); diff --git a/test/ports-map.js b/test/ports-map.js index b2946f5711..d7534ede1e 100644 --- a/test/ports-map.js +++ b/test/ports-map.js @@ -13,7 +13,7 @@ const listOfTests = { logging: 1, overlay: 1, progress: 1, - 'web-socket-server-and-transport.test': 1, + 'web-socket-server-and-transport': 1, 'web-socket-server-url': 2, // integration tests 'module-federation': 1, @@ -46,7 +46,24 @@ const listOfTests = { 'sockjs-server': 1, 'web-socket-server': 1, routes: 1, - 'web-socket-heartbeat': 1, + 'web-socket-communication': 1, + ipc: 1, + stats: 1, + 'cli-allowed-hosts': 1, + 'cli-bonjour': 1, + 'cli-client': 1, + 'cli-colors': 1, + 'cli-compress': 1, + 'cli-history-api-fallback': 1, + 'cli-host': 1, + 'cli-hot': 1, + 'cli-http2': 1, + 'cli-https': 1, + 'cli-live-reload': 1, + 'cli-open': 1, + 'cli-static': 1, + 'cli-watch-files': 1, + 'cli-web-socket-server': 1, }; let startPort = 8089; diff --git a/test/server/utils/__snapshots__/normalizeOptions.test.js.snap.webpack4 b/test/server/utils/__snapshots__/normalizeOptions.test.js.snap.webpack4 index 2cb67fd28e..87c7a25a32 100644 --- a/test/server/utils/__snapshots__/normalizeOptions.test.js.snap.webpack4 +++ b/test/server/utils/__snapshots__/normalizeOptions.test.js.snap.webpack4 @@ -288,7 +288,7 @@ Object { "options": Object { "host": "myhost", "path": "/ws", - "port": 8080, + "port": 9999, }, "type": "ws", }, diff --git a/test/server/utils/__snapshots__/normalizeOptions.test.js.snap.webpack5 b/test/server/utils/__snapshots__/normalizeOptions.test.js.snap.webpack5 index 2cb67fd28e..87c7a25a32 100644 --- a/test/server/utils/__snapshots__/normalizeOptions.test.js.snap.webpack5 +++ b/test/server/utils/__snapshots__/normalizeOptions.test.js.snap.webpack5 @@ -288,7 +288,7 @@ Object { "options": Object { "host": "myhost", "path": "/ws", - "port": 8080, + "port": 9999, }, "type": "ws", }, diff --git a/test/server/utils/normalizeOptions.test.js b/test/server/utils/normalizeOptions.test.js index 97389ecc74..401e7628ed 100644 --- a/test/server/utils/normalizeOptions.test.js +++ b/test/server/utils/normalizeOptions.test.js @@ -78,7 +78,7 @@ describe('normalizeOptions', () => { type: 'ws', options: { host: 'myhost', - port: 8080, + port: 9999, path: '/ws', }, }, diff --git a/test/server/watchFiles-option.test.js b/test/server/watchFiles-option.test.js index 0f3c71388c..aac4046b6d 100644 --- a/test/server/watchFiles-option.test.js +++ b/test/server/watchFiles-option.test.js @@ -173,6 +173,12 @@ describe("'watchFiles' option", () => { const nonExistFile = path.join(watchDir, 'assets/non-exist.txt'); beforeAll(async () => { + try { + fs.unlinkSync(nonExistFile); + } catch (error) { + // ignore + } + const compiler = webpack(config); server = new Server( @@ -213,9 +219,14 @@ describe("'watchFiles' option", () => { done(); }); - // change file content + // create file content setTimeout(() => { fs.writeFileSync(nonExistFile, 'Kurosaki Ichigo', 'utf8'); + + // change file content + setTimeout(() => { + fs.writeFileSync(nonExistFile, 'Kurosaki Ichigo', 'utf8'); + }, 1000); }, 1000); }); }); diff --git a/test/validate-options.test.js b/test/validate-options.test.js index fd0ef61c6e..7b50e0248e 100644 --- a/test/validate-options.test.js +++ b/test/validate-options.test.js @@ -1,13 +1,14 @@ 'use strict'; -const { join } = require('path'); +const os = require('os'); +const path = require('path'); const { readFileSync } = require('graceful-fs'); const webpack = require('webpack'); const { createFsFromVolume, Volume } = require('memfs'); const Server = require('../lib/Server'); const config = require('./fixtures/simple-config/webpack.config'); -const httpsCertificateDirectory = join( +const httpsCertificateDirectory = path.join( __dirname, './fixtures/https-certificate' ); @@ -204,18 +205,18 @@ const tests = { false, true, { - cacert: join(httpsCertificateDirectory, 'ca.pem'), - key: join(httpsCertificateDirectory, 'server.key'), - pfx: join(httpsCertificateDirectory, 'server.pfx'), - cert: join(httpsCertificateDirectory, 'server.crt'), + cacert: path.join(httpsCertificateDirectory, 'ca.pem'), + key: path.join(httpsCertificateDirectory, 'server.key'), + pfx: path.join(httpsCertificateDirectory, 'server.pfx'), + cert: path.join(httpsCertificateDirectory, 'server.crt'), requestCert: true, passphrase: 'webpack-dev-server', }, { - cacert: readFileSync(join(httpsCertificateDirectory, 'ca.pem')), - pfx: readFileSync(join(httpsCertificateDirectory, 'server.pfx')), - key: readFileSync(join(httpsCertificateDirectory, 'server.key')), - cert: readFileSync(join(httpsCertificateDirectory, 'server.crt')), + cacert: readFileSync(path.join(httpsCertificateDirectory, 'ca.pem')), + pfx: readFileSync(path.join(httpsCertificateDirectory, 'server.pfx')), + key: readFileSync(path.join(httpsCertificateDirectory, 'server.key')), + cert: readFileSync(path.join(httpsCertificateDirectory, 'server.crt')), passphrase: 'webpack-dev-server', }, ], @@ -244,6 +245,10 @@ const tests = { }, ], }, + ipc: { + success: [true, path.resolve(os.tmpdir(), 'webpack-dev-server.socket')], + failure: [false, {}], + }, onListening: { success: [() => {}], failure: [''], @@ -269,7 +274,7 @@ const tests = { failure: ['', { foo: 'bar' }, { target: 90 }, { app: true }], }, port: { - success: ['8080', 8080, 'auto'], + success: ['20000', 20001, 'auto'], failure: [false, null, ''], }, proxy: { @@ -450,7 +455,7 @@ describe('options', () => { // We need to patch memfs // https://github.com/webpack/webpack-dev-middleware#fs - memfs.join = join; + memfs.join = path.join; for (const [key, values] of Object.entries(tests)) { for (const type of Object.keys(values)) {