From 35ef2f5d5ba5058b87352975806ae7ed2bd3e432 Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Thu, 24 Jun 2021 00:38:29 +0300 Subject: [PATCH 01/31] feat: ipc --- bin/cli-flags.js | 23 ++ lib/Server.js | 238 +++++++++++------- lib/options.json | 17 +- lib/utils/normalizeOptions.js | 4 + package-lock.json | 1 + package.json | 1 + .../validate-options.test.js.snap.webpack5 | 21 ++ .../__snapshots__/basic.test.js.snap.webpack5 | 1 + .../ipc-option.test.js.snap.webpack5 | 11 + test/cli/ipc-option.test.js | 23 ++ .../__snapshots__/ipc.test.js.snap.webpack4 | 45 ++++ .../__snapshots__/ipc.test.js.snap.webpack5 | 45 ++++ test/e2e/ipc.test.js | 236 +++++++++++++++++ test/helpers/test-bin.js | 4 +- test/ports-map.js | 1 + test/validate-options.test.js | 27 +- 16 files changed, 590 insertions(+), 108 deletions(-) create mode 100644 test/cli/__snapshots__/ipc-option.test.js.snap.webpack5 create mode 100644 test/cli/ipc-option.test.js create mode 100644 test/e2e/__snapshots__/ipc.test.js.snap.webpack4 create mode 100644 test/e2e/__snapshots__/ipc.test.js.snap.webpack5 create mode 100644 test/e2e/ipc.test.js 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..9ae9d84499 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,73 @@ 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') { + // No other server listening on this socket so it can be safely removed + 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 portOrIPCPath = this.options.ipc + ? this.options.ipc + : this.options.port; - if (this.options.bonjour) { - this.runBonjour(); - } + return this.server.listen(portOrIPCPath, this.options.host, (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..2bd224184b 100644 --- a/lib/utils/normalizeOptions.js +++ b/lib/utils/normalizeOptions.js @@ -219,6 +219,10 @@ function normalizeOptions(compiler, options, logger, cacheDir) { options.https.cert = options.https.cert || fakeCert; } + if (typeof options.ipc === 'boolean') { + options.ipc = path.resolve(os.tmpdir(), 'webpack-dev-server.socket'); + } + 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/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.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.webpack5 b/test/cli/__snapshots__/ipc-option.test.js.snap.webpack5 new file mode 100644 index 0000000000..f822ba750c --- /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.socket\\" + [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.socket\\" + [webpack-dev-server] Content not from webpack is served from '/public' directory" +`; diff --git a/test/cli/ipc-option.test.js b/test/cli/ipc-option.test.js new file mode 100644 index 0000000000..9345c857c3 --- /dev/null +++ b/test/cli/ipc-option.test.js @@ -0,0 +1,23 @@ +'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 ipc = path.resolve(os.tmpdir(), 'webpack-dev-server.socket'); + + const { exitCode, stderr } = await testBin(['--ipc', ipc]); + + expect(exitCode).toEqual(0); + expect(normalizeStderr(stderr)).toMatchSnapshot('stderr'); + }); +}); 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..35f6a2d410 --- /dev/null +++ b/test/e2e/ipc.test.js @@ -0,0 +1,236 @@ +'use strict'; + +const os = require('os'); +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); + + await new Promise((resolve, reject) => { + server.listen((error) => { + if (error) { + reject(error); + + return; + } + + resolve(); + }); + }); + + function startProxy(callback) { + const proxy = httpProxy.createProxyServer({ + target: { socketPath: '/tmp/webpack-dev-server.socket' }, + }); + + 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 devServerHost = '127.0.0.1'; + const proxyHost = devServerHost; + const proxyPort = port1; + const ipc = path.resolve(os.tmpdir(), 'webpack-dev-server.socket'); + + 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: '/tmp/webpack-dev-server.socket' }, + }); + + 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(); + }); + }); + }); + } +}); diff --git a/test/helpers/test-bin.js b/test/helpers/test-bin.js index 078019cb73..cdd16a3cdc 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,8 @@ 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'), ''); const networkIPv4 = internalIp.v4.sync(); diff --git a/test/ports-map.js b/test/ports-map.js index b2946f5711..9daefb0091 100644 --- a/test/ports-map.js +++ b/test/ports-map.js @@ -47,6 +47,7 @@ const listOfTests = { 'web-socket-server': 1, routes: 1, 'web-socket-heartbeat': 1, + ipc: 1, }; let startPort = 8089; diff --git a/test/validate-options.test.js b/test/validate-options.test.js index fd0ef61c6e..686b7e06f5 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: [''], @@ -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)) { From a13a38835ccd8a09b396602450f8ad4a5017abf8 Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Thu, 24 Jun 2021 00:46:11 +0300 Subject: [PATCH 02/31] docs: update readme --- README.md | 1 + 1 file changed, 1 insertion(+) 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. From 90c90bdcd7f39d22f0403b7e437d72aa80d81fae Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Thu, 24 Jun 2021 00:54:33 +0300 Subject: [PATCH 03/31] refactor: code --- lib/Server.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/lib/Server.js b/lib/Server.js index 9ae9d84499..988d590a2b 100644 --- a/lib/Server.js +++ b/lib/Server.js @@ -967,11 +967,14 @@ class Server { .then(() => { this.initialize(); - const portOrIPCPath = this.options.ipc - ? this.options.ipc - : this.options.port; - - return this.server.listen(portOrIPCPath, this.options.host, (error) => { + const listenOptions = this.options.ipc + ? { path: this.options.ipc } + : { + host: this.options.host, + port: this.options.port, + }; + + return this.server.listen(listenOptions, (error) => { if (this.options.ipc) { // chmod 666 (rw rw rw) const READ_WRITE = 438; From b31a2164ada89d4894d2b8fd22e7ac4cd9902772 Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Thu, 24 Jun 2021 01:05:03 +0300 Subject: [PATCH 04/31] test: fix snapshots --- .../validate-options.test.js.snap.webpack4 | 21 +++++++++++++++++++ .../__snapshots__/basic.test.js.snap.webpack4 | 1 + .../ipc-option.test.js.snap.webpack4 | 11 ++++++++++ 3 files changed, 33 insertions(+) create mode 100644 test/cli/__snapshots__/ipc-option.test.js.snap.webpack4 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/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__/ipc-option.test.js.snap.webpack4 b/test/cli/__snapshots__/ipc-option.test.js.snap.webpack4 new file mode 100644 index 0000000000..f822ba750c --- /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.socket\\" + [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.socket\\" + [webpack-dev-server] Content not from webpack is served from '/public' directory" +`; From 68b19a7c6208519185863fd24f7eecdbb323fb52 Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Thu, 24 Jun 2021 02:21:44 +0300 Subject: [PATCH 05/31] test: fix --- test/e2e/ipc.test.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/test/e2e/ipc.test.js b/test/e2e/ipc.test.js index 35f6a2d410..854eded7f9 100644 --- a/test/e2e/ipc.test.js +++ b/test/e2e/ipc.test.js @@ -1,6 +1,7 @@ 'use strict'; const os = require('os'); +const fs = require('fs'); const path = require('path'); const http = require('http'); const webpack = require('webpack'); @@ -16,7 +17,11 @@ describe('web socket server URL', () => { for (const webSocketServer of webSocketServers) { const websocketURLProtocol = webSocketServer === 'ws' ? 'ws' : 'http'; + const ipc = path.resolve(os.tmpdir(), 'webpack-dev-server.socket'); + it(`should work with the "ipc" option using "true" value ("${webSocketServer}")`, async () => { + fs.unlinkSync(ipc); + const devServerHost = '127.0.0.1'; const proxyHost = devServerHost; const proxyPort = port1; @@ -125,10 +130,11 @@ describe('web socket server URL', () => { }); it(`should work with the "ipc" option using "string" value ("${webSocketServer}")`, async () => { + fs.unlinkSync(ipc); + const devServerHost = '127.0.0.1'; const proxyHost = devServerHost; const proxyPort = port1; - const ipc = path.resolve(os.tmpdir(), 'webpack-dev-server.socket'); const compiler = webpack(config); const devServerOptions = { From 0223e4f41ad943829aadeb2855130bc39490bfe6 Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Thu, 24 Jun 2021 02:29:01 +0300 Subject: [PATCH 06/31] test: fix --- test/e2e/ipc.test.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/test/e2e/ipc.test.js b/test/e2e/ipc.test.js index 854eded7f9..b04c34290b 100644 --- a/test/e2e/ipc.test.js +++ b/test/e2e/ipc.test.js @@ -20,7 +20,11 @@ describe('web socket server URL', () => { const ipc = path.resolve(os.tmpdir(), 'webpack-dev-server.socket'); it(`should work with the "ipc" option using "true" value ("${webSocketServer}")`, async () => { - fs.unlinkSync(ipc); + try { + fs.unlinkSync(ipc); + } catch (_error) { + // Ignore + } const devServerHost = '127.0.0.1'; const proxyHost = devServerHost; @@ -130,7 +134,11 @@ describe('web socket server URL', () => { }); it(`should work with the "ipc" option using "string" value ("${webSocketServer}")`, async () => { - fs.unlinkSync(ipc); + try { + fs.unlinkSync(ipc); + } catch (_error) { + // Ignore + } const devServerHost = '127.0.0.1'; const proxyHost = devServerHost; From d6eb45b3a7e3454cfaa5214ea68a5270cca1c1ba Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Thu, 24 Jun 2021 02:29:21 +0300 Subject: [PATCH 07/31] test: fix --- test/e2e/stats.test.js | 2 +- test/ports-map.js | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) 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/ports-map.js b/test/ports-map.js index 9daefb0091..27b9a1c62d 100644 --- a/test/ports-map.js +++ b/test/ports-map.js @@ -48,6 +48,7 @@ const listOfTests = { routes: 1, 'web-socket-heartbeat': 1, ipc: 1, + stats: 1, }; let startPort = 8089; From 4df834ecf872beaf46298d58340ead7a08b6c339 Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Thu, 24 Jun 2021 02:31:37 +0300 Subject: [PATCH 08/31] test: fix --- test/e2e/web-socket-communication.test.js | 2 +- test/e2e/web-socket-server-and-transport.test.js | 2 +- test/ports-map.js | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) 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/ports-map.js b/test/ports-map.js index 27b9a1c62d..f02bc85349 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,7 @@ const listOfTests = { 'sockjs-server': 1, 'web-socket-server': 1, routes: 1, - 'web-socket-heartbeat': 1, + 'web-socket-communication': 1, ipc: 1, stats: 1, }; From fbd9fd38edac19f6480ba5dfbe75eb17f6b96858 Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Thu, 24 Jun 2021 02:53:45 +0300 Subject: [PATCH 09/31] fix: windows supports --- lib/utils/normalizeOptions.js | 7 +- .../__snapshots__/ipc.test.js.snap.webpack4 | 22 +++ .../__snapshots__/ipc.test.js.snap.webpack5 | 22 +++ test/e2e/ipc.test.js | 136 ++++++++++++++++-- 4 files changed, 172 insertions(+), 15 deletions(-) diff --git a/lib/utils/normalizeOptions.js b/lib/utils/normalizeOptions.js index 2bd224184b..71441b9b60 100644 --- a/lib/utils/normalizeOptions.js +++ b/lib/utils/normalizeOptions.js @@ -220,7 +220,12 @@ function normalizeOptions(compiler, options, logger, cacheDir) { } if (typeof options.ipc === 'boolean') { - options.ipc = path.resolve(os.tmpdir(), 'webpack-dev-server.socket'); + 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}.sock`; + + options.ipc = path.join(pipePrefix, pipeName); } options.liveReload = diff --git a/test/e2e/__snapshots__/ipc.test.js.snap.webpack4 b/test/e2e/__snapshots__/ipc.test.js.snap.webpack4 index e31bdaa38e..a420dd8bfb 100644 --- a/test/e2e/__snapshots__/ipc.test.js.snap.webpack4 +++ b/test/e2e/__snapshots__/ipc.test.js.snap.webpack4 @@ -22,6 +22,28 @@ Array [ 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 "string" value and remove old ("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 and remove old ("sockjs"): page errors 1`] = `Array []`; + +exports[`web socket server URL should work with the "ipc" option using "string" value and remove old ("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 and remove old ("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...", diff --git a/test/e2e/__snapshots__/ipc.test.js.snap.webpack5 b/test/e2e/__snapshots__/ipc.test.js.snap.webpack5 index e31bdaa38e..a420dd8bfb 100644 --- a/test/e2e/__snapshots__/ipc.test.js.snap.webpack5 +++ b/test/e2e/__snapshots__/ipc.test.js.snap.webpack5 @@ -22,6 +22,28 @@ Array [ 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 "string" value and remove old ("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 and remove old ("sockjs"): page errors 1`] = `Array []`; + +exports[`web socket server URL should work with the "ipc" option using "string" value and remove old ("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 and remove old ("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...", diff --git a/test/e2e/ipc.test.js b/test/e2e/ipc.test.js index b04c34290b..7673757b35 100644 --- a/test/e2e/ipc.test.js +++ b/test/e2e/ipc.test.js @@ -17,15 +17,7 @@ describe('web socket server URL', () => { for (const webSocketServer of webSocketServers) { const websocketURLProtocol = webSocketServer === 'ws' ? 'ws' : 'http'; - const ipc = path.resolve(os.tmpdir(), 'webpack-dev-server.socket'); - it(`should work with the "ipc" option using "true" value ("${webSocketServer}")`, async () => { - try { - fs.unlinkSync(ipc); - } catch (_error) { - // Ignore - } - const devServerHost = '127.0.0.1'; const proxyHost = devServerHost; const proxyPort = port1; @@ -52,7 +44,7 @@ describe('web socket server URL', () => { function startProxy(callback) { const proxy = httpProxy.createProxyServer({ - target: { socketPath: '/tmp/webpack-dev-server.socket' }, + target: { socketPath: server.options.ipc }, }); const proxyServer = http.createServer((request, response) => { @@ -134,12 +126,128 @@ describe('web socket server URL', () => { }); it(`should work with the "ipc" option using "string" value ("${webSocketServer}")`, async () => { - try { - fs.unlinkSync(ipc); - } catch (_error) { - // Ignore + const isWindows = process.platform === 'win32'; + const localRelative = path.relative(process.cwd(), `${os.tmpdir()}/`); + const pipePrefix = isWindows ? '\\\\.\\pipe\\' : localRelative; + const pipeName = `webpack-dev-server.custom.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(); + }); + }); + }); + + it(`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.other-custom.sock`; + const ipc = path.join(pipePrefix, pipeName); + + fs.writeFileSync(ipc, ''); + const devServerHost = '127.0.0.1'; const proxyHost = devServerHost; const proxyPort = port1; @@ -166,7 +274,7 @@ describe('web socket server URL', () => { function startProxy(callback) { const proxy = httpProxy.createProxyServer({ - target: { socketPath: '/tmp/webpack-dev-server.socket' }, + target: { socketPath: ipc }, }); const proxyServer = http.createServer((request, response) => { From 1668629f59be2910cf3c2678813723cdbd5fbe66 Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Thu, 24 Jun 2021 02:54:26 +0300 Subject: [PATCH 10/31] test: fix cli --- test/cli/ipc-option.test.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/cli/ipc-option.test.js b/test/cli/ipc-option.test.js index 9345c857c3..2a20c6aebb 100644 --- a/test/cli/ipc-option.test.js +++ b/test/cli/ipc-option.test.js @@ -13,7 +13,11 @@ describe('"ipc" CLI option', () => { }); it('should work using "--ipc="', async () => { - const ipc = path.resolve(os.tmpdir(), 'webpack-dev-server.socket'); + const isWindows = process.platform === 'win32'; + const localRelative = path.relative(process.cwd(), `${os.tmpdir()}/`); + const pipePrefix = isWindows ? '\\\\.\\pipe\\' : localRelative; + const pipeName = `webpack-dev-server.cli.sock`; + const ipc = path.join(pipePrefix, pipeName); const { exitCode, stderr } = await testBin(['--ipc', ipc]); From 2fd5fa29db5d2f68edf9d827c756ff30ef30ee34 Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Thu, 24 Jun 2021 04:01:48 +0300 Subject: [PATCH 11/31] refactor: code and test --- lib/Server.js | 1 - lib/utils/normalizeOptions.js | 2 +- .../ipc-option.test.js.snap.webpack4 | 4 +- .../ipc-option.test.js.snap.webpack5 | 4 +- .../__snapshots__/ipc.test.js.snap.webpack4 | 44 ------------------- .../__snapshots__/ipc.test.js.snap.webpack5 | 44 ------------------- test/e2e/ipc.test.js | 36 ++++++++++++--- test/helpers/test-bin.js | 6 ++- 8 files changed, 40 insertions(+), 101 deletions(-) diff --git a/lib/Server.js b/lib/Server.js index 988d590a2b..80eb1fe858 100644 --- a/lib/Server.js +++ b/lib/Server.js @@ -937,7 +937,6 @@ class Server { socket.on('error', (error) => { if (error.code === 'ECONNREFUSED') { - // No other server listening on this socket so it can be safely removed fs.unlinkSync(this.options.ipc); resolve(this.options.ipc); diff --git a/lib/utils/normalizeOptions.js b/lib/utils/normalizeOptions.js index 71441b9b60..01a67db0f6 100644 --- a/lib/utils/normalizeOptions.js +++ b/lib/utils/normalizeOptions.js @@ -223,7 +223,7 @@ function normalizeOptions(compiler, options, logger, cacheDir) { 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}.sock`; + const pipeName = `webpack-dev-server.sock`; options.ipc = path.join(pipePrefix, pipeName); } diff --git a/test/cli/__snapshots__/ipc-option.test.js.snap.webpack4 b/test/cli/__snapshots__/ipc-option.test.js.snap.webpack4 index f822ba750c..ffb1b9a9ce 100644 --- a/test/cli/__snapshots__/ipc-option.test.js.snap.webpack4 +++ b/test/cli/__snapshots__/ipc-option.test.js.snap.webpack4 @@ -1,11 +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.socket\\" +" [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.socket\\" +" [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 index f822ba750c..ffb1b9a9ce 100644 --- a/test/cli/__snapshots__/ipc-option.test.js.snap.webpack5 +++ b/test/cli/__snapshots__/ipc-option.test.js.snap.webpack5 @@ -1,11 +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.socket\\" +" [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.socket\\" +" [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/e2e/__snapshots__/ipc.test.js.snap.webpack4 b/test/e2e/__snapshots__/ipc.test.js.snap.webpack4 index a420dd8bfb..d57977d3a4 100644 --- a/test/e2e/__snapshots__/ipc.test.js.snap.webpack4 +++ b/test/e2e/__snapshots__/ipc.test.js.snap.webpack4 @@ -1,16 +1,5 @@ // 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...", @@ -22,39 +11,6 @@ Array [ 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 "string" value and remove old ("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 and remove old ("sockjs"): page errors 1`] = `Array []`; - -exports[`web socket server URL should work with the "ipc" option using "string" value and remove old ("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 and remove old ("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...", diff --git a/test/e2e/__snapshots__/ipc.test.js.snap.webpack5 b/test/e2e/__snapshots__/ipc.test.js.snap.webpack5 index a420dd8bfb..d57977d3a4 100644 --- a/test/e2e/__snapshots__/ipc.test.js.snap.webpack5 +++ b/test/e2e/__snapshots__/ipc.test.js.snap.webpack5 @@ -1,16 +1,5 @@ // 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...", @@ -22,39 +11,6 @@ Array [ 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 "string" value and remove old ("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 and remove old ("sockjs"): page errors 1`] = `Array []`; - -exports[`web socket server URL should work with the "ipc" option using "string" value and remove old ("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 and remove old ("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...", diff --git a/test/e2e/ipc.test.js b/test/e2e/ipc.test.js index 7673757b35..2491e75b7a 100644 --- a/test/e2e/ipc.test.js +++ b/test/e2e/ipc.test.js @@ -1,7 +1,7 @@ 'use strict'; const os = require('os'); -const fs = require('fs'); +const net = require('net'); const path = require('path'); const http = require('http'); const webpack = require('webpack'); @@ -11,7 +11,7 @@ const config = require('../fixtures/client-config/webpack.config'); const runBrowser = require('../helpers/run-browser'); const port1 = require('../ports-map').ipc; -const webSocketServers = ['ws', 'sockjs']; +const webSocketServers = ['ws']; describe('web socket server URL', () => { for (const webSocketServer of webSocketServers) { @@ -129,7 +129,7 @@ describe('web socket server URL', () => { const isWindows = process.platform === 'win32'; const localRelative = path.relative(process.cwd(), `${os.tmpdir()}/`); const pipePrefix = isWindows ? '\\\\.\\pipe\\' : localRelative; - const pipeName = `webpack-dev-server.custom.sock`; + const pipeName = `webpack-dev-server.${process.pid}-1.sock`; const ipc = path.join(pipePrefix, pipeName); const devServerHost = '127.0.0.1'; @@ -239,14 +239,25 @@ describe('web socket server URL', () => { }); }); - it(`should work with the "ipc" option using "string" value and remove old ("${webSocketServer}")`, async () => { + // 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.other-custom.sock`; + const pipeName = `webpack-dev-server.${process.pid}-2.sock`; const ipc = path.join(pipePrefix, pipeName); - fs.writeFileSync(ipc, ''); + 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; @@ -290,6 +301,7 @@ describe('web socket server URL', () => { return proxyServer.listen(proxyPort, proxyHost, callback); } + console.log('HERE'); const proxy = await new Promise((resolve) => { const proxyCreated = startProxy(() => { resolve(proxyCreated); @@ -325,6 +337,7 @@ describe('web socket server URL', () => { }); } + console.log(`http://${proxyHost}:${proxyPort}/main`); await page.goto(`http://${proxyHost}:${proxyPort}/main`, { waitUntil: 'networkidle0', }); @@ -341,6 +354,17 @@ describe('web socket server URL', () => { 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) => { diff --git a/test/helpers/test-bin.js b/test/helpers/test-bin.js index cdd16a3cdc..3811da72d0 100644 --- a/test/helpers/test-bin.js +++ b/test/helpers/test-bin.js @@ -45,10 +45,14 @@ const testBin = (testArgs, configPath) => { const normalizeStderr = (stderr, options = {}) => { let normalizedStderr = stripAnsi(stderr); + const isWindows = process.platform === 'win32'; + const localRelative = path.relative(process.cwd(), `${os.tmpdir()}/`); + const pipeRoot = isWindows ? '\\\\.\\pipe\\' : localRelative; + normalizedStderr = normalizedStderr .replace(/\\/g, '/') .replace(new RegExp(process.cwd().replace(/\\/g, '/'), 'g'), '') - .replace(new RegExp(os.tmpdir().replace(/\\/g, '/'), 'g'), ''); + .replace(new RegExp(pipeRoot.replace(/\\/g, '/'), 'g'), ''); const networkIPv4 = internalIp.v4.sync(); From f2247afa2c03442651f14eb4ba1f1bae37412519 Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Thu, 24 Jun 2021 04:25:35 +0300 Subject: [PATCH 12/31] test: fix --- test/helpers/test-bin.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/helpers/test-bin.js b/test/helpers/test-bin.js index 3811da72d0..2a0e0aacd8 100644 --- a/test/helpers/test-bin.js +++ b/test/helpers/test-bin.js @@ -52,7 +52,10 @@ const normalizeStderr = (stderr, options = {}) => { normalizedStderr = normalizedStderr .replace(/\\/g, '/') .replace(new RegExp(process.cwd().replace(/\\/g, '/'), 'g'), '') - .replace(new RegExp(pipeRoot.replace(/\\/g, '/'), 'g'), ''); + .replace( + new RegExp(pipeRoot.replace(/\\/g, '/'), 'g'), + `${isWindows ? '/' : ''}` + ); const networkIPv4 = internalIp.v4.sync(); From eb46756234473d0ebce5308b144ceec12eecfffb Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Thu, 24 Jun 2021 17:15:00 +0300 Subject: [PATCH 13/31] test: fix --- .../__snapshots__/ipc.test.js.snap.webpack4 | 22 +++++++++++++++++++ .../__snapshots__/ipc.test.js.snap.webpack5 | 22 +++++++++++++++++++ test/e2e/ipc.test.js | 8 ++++++- 3 files changed, 51 insertions(+), 1 deletion(-) diff --git a/test/e2e/__snapshots__/ipc.test.js.snap.webpack4 b/test/e2e/__snapshots__/ipc.test.js.snap.webpack4 index d57977d3a4..e31bdaa38e 100644 --- a/test/e2e/__snapshots__/ipc.test.js.snap.webpack4 +++ b/test/e2e/__snapshots__/ipc.test.js.snap.webpack4 @@ -1,5 +1,16 @@ // 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...", @@ -11,6 +22,17 @@ Array [ 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...", diff --git a/test/e2e/__snapshots__/ipc.test.js.snap.webpack5 b/test/e2e/__snapshots__/ipc.test.js.snap.webpack5 index d57977d3a4..e31bdaa38e 100644 --- a/test/e2e/__snapshots__/ipc.test.js.snap.webpack5 +++ b/test/e2e/__snapshots__/ipc.test.js.snap.webpack5 @@ -1,5 +1,16 @@ // 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...", @@ -11,6 +22,17 @@ Array [ 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...", diff --git a/test/e2e/ipc.test.js b/test/e2e/ipc.test.js index 2491e75b7a..1f65a9ed95 100644 --- a/test/e2e/ipc.test.js +++ b/test/e2e/ipc.test.js @@ -11,7 +11,7 @@ const config = require('../fixtures/client-config/webpack.config'); const runBrowser = require('../helpers/run-browser'); const port1 = require('../ports-map').ipc; -const webSocketServers = ['ws']; +const webSocketServers = ['ws', 'sockjs']; describe('web socket server URL', () => { for (const webSocketServer of webSocketServers) { @@ -30,6 +30,12 @@ describe('web socket server URL', () => { }; 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}-1` + ); + await new Promise((resolve, reject) => { server.listen((error) => { if (error) { From abcc980d6c0489970885ca6703ec24eb1a49a626 Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Thu, 24 Jun 2021 17:19:37 +0300 Subject: [PATCH 14/31] fix: compatibility with libuv --- lib/Server.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/Server.js b/lib/Server.js index 80eb1fe858..0b1e4c3299 100644 --- a/lib/Server.js +++ b/lib/Server.js @@ -942,7 +942,9 @@ class Server { resolve(this.options.ipc); return; - } else if (error.code === 'ENOENT') { + } + // https://github.com/nodejs/node/issues/35538 + else if (error.code === 'ENOENT' || error.code === 'EACCES') { resolve(this.options.ipc); return; From 6dd7b9a3b266c9630c795e6e122f50a53d8a5d25 Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Thu, 24 Jun 2021 18:56:58 +0300 Subject: [PATCH 15/31] test: debug --- lib/Server.js | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/lib/Server.js b/lib/Server.js index 0b1e4c3299..241ff083f7 100644 --- a/lib/Server.js +++ b/lib/Server.js @@ -936,15 +936,37 @@ class Server { const socket = new net.Socket(); socket.on('error', (error) => { + try { + fs.accessSync(this.options.ipc); + } catch (one) { + // eslint-disable-next-line no-console + console.log('ONE'); + // eslint-disable-next-line no-console + console.log(one); + } + + try { + fs.accessSync( + path.dirname(this.options.ipc), + // eslint-disable-next-line no-bitwise + fs.constants.R_OK | fs.constants.W_OK + ); + // eslint-disable-next-line no-console + console.log('can access'); + } catch (two) { + // eslint-disable-next-line no-console + console.log('TWO'); + // eslint-disable-next-line no-console + console.log(two); + } + if (error.code === 'ECONNREFUSED') { fs.unlinkSync(this.options.ipc); resolve(this.options.ipc); return; - } - // https://github.com/nodejs/node/issues/35538 - else if (error.code === 'ENOENT' || error.code === 'EACCES') { + } else if (error.code === 'ENOENT') { resolve(this.options.ipc); return; From ab7152b9fcbd92386eef808504e0089fe8b10c73 Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Thu, 24 Jun 2021 20:05:35 +0300 Subject: [PATCH 16/31] test: debug --- lib/Server.js | 25 ++----------------------- 1 file changed, 2 insertions(+), 23 deletions(-) diff --git a/lib/Server.js b/lib/Server.js index 241ff083f7..d9061ee6f7 100644 --- a/lib/Server.js +++ b/lib/Server.js @@ -936,29 +936,8 @@ class Server { const socket = new net.Socket(); socket.on('error', (error) => { - try { - fs.accessSync(this.options.ipc); - } catch (one) { - // eslint-disable-next-line no-console - console.log('ONE'); - // eslint-disable-next-line no-console - console.log(one); - } - - try { - fs.accessSync( - path.dirname(this.options.ipc), - // eslint-disable-next-line no-bitwise - fs.constants.R_OK | fs.constants.W_OK - ); - // eslint-disable-next-line no-console - console.log('can access'); - } catch (two) { - // eslint-disable-next-line no-console - console.log('TWO'); - // eslint-disable-next-line no-console - console.log(two); - } + // eslint-disable-next-line no-console + console.log('TEST ERROR', error); if (error.code === 'ECONNREFUSED') { fs.unlinkSync(this.options.ipc); From c115054442c373c1a19e325d5cc4716619622c3d Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Thu, 24 Jun 2021 20:25:57 +0300 Subject: [PATCH 17/31] test: debug speedup --- .github/workflows/nodejs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 3d2bd8739e..eeb3f04d00 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -105,7 +105,7 @@ jobs: npm link webpack-dev-server - name: Run tests for webpack version ${{ matrix.webpack-version }} - run: npm run test:coverage -- --ci + run: node_modules/.bin/jest test/e2e/ipc.test.js --ci - name: Submit coverage data to codecov uses: codecov/codecov-action@v1 From 1781b2ed5aeebbc3b84dd851060132410b61086f Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Thu, 24 Jun 2021 20:52:03 +0300 Subject: [PATCH 18/31] test: debug speedup --- setupTest.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/setupTest.js b/setupTest.js index 438bcc143b..c1bc3537af 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(10000); From ce53763a922e4057b1286575b45f427ae152b779 Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Thu, 24 Jun 2021 20:59:58 +0300 Subject: [PATCH 19/31] test: debug --- .../__snapshots__/ipc.test.js.snap.webpack4 | 22 ------------------- .../__snapshots__/ipc.test.js.snap.webpack5 | 22 ------------------- test/e2e/ipc.test.js | 4 ++-- 3 files changed, 2 insertions(+), 46 deletions(-) diff --git a/test/e2e/__snapshots__/ipc.test.js.snap.webpack4 b/test/e2e/__snapshots__/ipc.test.js.snap.webpack4 index e31bdaa38e..aa90485da8 100644 --- a/test/e2e/__snapshots__/ipc.test.js.snap.webpack4 +++ b/test/e2e/__snapshots__/ipc.test.js.snap.webpack4 @@ -21,25 +21,3 @@ Array [ `; 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 index e31bdaa38e..aa90485da8 100644 --- a/test/e2e/__snapshots__/ipc.test.js.snap.webpack5 +++ b/test/e2e/__snapshots__/ipc.test.js.snap.webpack5 @@ -21,25 +21,3 @@ Array [ `; 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 index 1f65a9ed95..4d9a83aaec 100644 --- a/test/e2e/ipc.test.js +++ b/test/e2e/ipc.test.js @@ -131,9 +131,9 @@ describe('web socket server URL', () => { }); }); - it(`should work with the "ipc" option using "string" value ("${webSocketServer}")`, async () => { + it.only(`should work with the "ipc" option using "string" value ("${webSocketServer}")`, async () => { const isWindows = process.platform === 'win32'; - const localRelative = path.relative(process.cwd(), `${os.tmpdir()}/`); + const localRelative = path.relative(process.cwd(), `${process.cwd()}/`); const pipePrefix = isWindows ? '\\\\.\\pipe\\' : localRelative; const pipeName = `webpack-dev-server.${process.pid}-1.sock`; const ipc = path.join(pipePrefix, pipeName); From 49f50e970365e8d7a915e0eaf7a9b91a267e22f5 Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Thu, 24 Jun 2021 22:01:31 +0300 Subject: [PATCH 20/31] test: debug --- lib/Server.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/Server.js b/lib/Server.js index d9061ee6f7..bb166ede48 100644 --- a/lib/Server.js +++ b/lib/Server.js @@ -976,11 +976,18 @@ class Server { port: this.options.port, }; + // eslint-disable-next-line no-console + console.log(listenOptions); + return this.server.listen(listenOptions, (error) => { + // eslint-disable-next-line no-console + console.log('LISTEN'); if (this.options.ipc) { // chmod 666 (rw rw rw) const READ_WRITE = 438; + // eslint-disable-next-line no-console + console.log('CHANGE CHMOD'); fs.chmodSync(this.options.ipc, READ_WRITE); } From 48d8761d60531cd9620b7918f9188cb76c6761cb Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Fri, 25 Jun 2021 15:52:11 +0300 Subject: [PATCH 21/31] test: debug --- lib/Server.js | 10 ---------- test/e2e/ipc.test.js | 2 +- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/lib/Server.js b/lib/Server.js index bb166ede48..80eb1fe858 100644 --- a/lib/Server.js +++ b/lib/Server.js @@ -936,9 +936,6 @@ class Server { const socket = new net.Socket(); socket.on('error', (error) => { - // eslint-disable-next-line no-console - console.log('TEST ERROR', error); - if (error.code === 'ECONNREFUSED') { fs.unlinkSync(this.options.ipc); @@ -976,18 +973,11 @@ class Server { port: this.options.port, }; - // eslint-disable-next-line no-console - console.log(listenOptions); - return this.server.listen(listenOptions, (error) => { - // eslint-disable-next-line no-console - console.log('LISTEN'); if (this.options.ipc) { // chmod 666 (rw rw rw) const READ_WRITE = 438; - // eslint-disable-next-line no-console - console.log('CHANGE CHMOD'); fs.chmodSync(this.options.ipc, READ_WRITE); } diff --git a/test/e2e/ipc.test.js b/test/e2e/ipc.test.js index 4d9a83aaec..1106e35348 100644 --- a/test/e2e/ipc.test.js +++ b/test/e2e/ipc.test.js @@ -133,7 +133,7 @@ describe('web socket server URL', () => { it.only(`should work with the "ipc" option using "string" value ("${webSocketServer}")`, async () => { const isWindows = process.platform === 'win32'; - const localRelative = path.relative(process.cwd(), `${process.cwd()}/`); + const localRelative = path.relative(process.cwd(), `${os.tmpdir()}/`); const pipePrefix = isWindows ? '\\\\.\\pipe\\' : localRelative; const pipeName = `webpack-dev-server.${process.pid}-1.sock`; const ipc = path.join(pipePrefix, pipeName); From 7aed664e80597d855f8d5ad17b7c9a9d13b5596e Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Fri, 25 Jun 2021 16:36:32 +0300 Subject: [PATCH 22/31] test: debug --- test/e2e/ipc.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/e2e/ipc.test.js b/test/e2e/ipc.test.js index 1106e35348..4d9a83aaec 100644 --- a/test/e2e/ipc.test.js +++ b/test/e2e/ipc.test.js @@ -133,7 +133,7 @@ describe('web socket server URL', () => { it.only(`should work with the "ipc" option using "string" value ("${webSocketServer}")`, async () => { const isWindows = process.platform === 'win32'; - const localRelative = path.relative(process.cwd(), `${os.tmpdir()}/`); + const localRelative = path.relative(process.cwd(), `${process.cwd()}/`); const pipePrefix = isWindows ? '\\\\.\\pipe\\' : localRelative; const pipeName = `webpack-dev-server.${process.pid}-1.sock`; const ipc = path.join(pipePrefix, pipeName); From a4526021e0ed9b9c6ea660bf280c827d0c8ce981 Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Fri, 25 Jun 2021 17:17:18 +0300 Subject: [PATCH 23/31] test: debug --- lib/utils/normalizeOptions.js | 5 ++--- test/e2e/ipc.test.js | 3 +-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/lib/utils/normalizeOptions.js b/lib/utils/normalizeOptions.js index 01a67db0f6..2234967a2d 100644 --- a/lib/utils/normalizeOptions.js +++ b/lib/utils/normalizeOptions.js @@ -221,9 +221,8 @@ function normalizeOptions(compiler, options, logger, cacheDir) { if (typeof options.ipc === 'boolean') { const isWindows = process.platform === 'win32'; - const localRelative = path.relative(process.cwd(), `${os.tmpdir()}/`); - const pipePrefix = isWindows ? '\\\\.\\pipe\\' : localRelative; - const pipeName = `webpack-dev-server.sock`; + const pipePrefix = isWindows ? '\\\\.\\pipe\\' : os.tmpdir(); + const pipeName = 'webpack-dev-server.sock'; options.ipc = path.join(pipePrefix, pipeName); } diff --git a/test/e2e/ipc.test.js b/test/e2e/ipc.test.js index 4d9a83aaec..8ca61ed6d4 100644 --- a/test/e2e/ipc.test.js +++ b/test/e2e/ipc.test.js @@ -133,8 +133,7 @@ describe('web socket server URL', () => { it.only(`should work with the "ipc" option using "string" value ("${webSocketServer}")`, async () => { const isWindows = process.platform === 'win32'; - const localRelative = path.relative(process.cwd(), `${process.cwd()}/`); - const pipePrefix = isWindows ? '\\\\.\\pipe\\' : localRelative; + const pipePrefix = isWindows ? '\\\\.\\pipe\\' : os.tmpdir(); const pipeName = `webpack-dev-server.${process.pid}-1.sock`; const ipc = path.join(pipePrefix, pipeName); From bd971487921721b1679fbba34c5b7ea6d88563de Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Fri, 25 Jun 2021 17:48:30 +0300 Subject: [PATCH 24/31] test: fix --- .github/workflows/nodejs.yml | 2 +- setupTest.js | 2 +- .../ipc-option.test.js.snap.webpack4 | 4 ++-- .../ipc-option.test.js.snap.webpack5 | 4 ++-- test/cli/ipc-option.test.js | 3 +-- .../__snapshots__/ipc.test.js.snap.webpack4 | 22 +++++++++++++++++++ .../__snapshots__/ipc.test.js.snap.webpack5 | 22 +++++++++++++++++++ test/e2e/ipc.test.js | 4 ++-- test/helpers/test-bin.js | 9 +------- 9 files changed, 54 insertions(+), 18 deletions(-) diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index eeb3f04d00..3d2bd8739e 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -105,7 +105,7 @@ jobs: npm link webpack-dev-server - name: Run tests for webpack version ${{ matrix.webpack-version }} - run: node_modules/.bin/jest test/e2e/ipc.test.js --ci + run: npm run test:coverage -- --ci - name: Submit coverage data to codecov uses: codecov/codecov-action@v1 diff --git a/setupTest.js b/setupTest.js index c1bc3537af..ee41cc92d0 100644 --- a/setupTest.js +++ b/setupTest.js @@ -2,4 +2,4 @@ process.env.CHOKIDAR_USEPOLLING = true; -jest.setTimeout(10000); +jest.setTimeout(90000); diff --git a/test/cli/__snapshots__/ipc-option.test.js.snap.webpack4 b/test/cli/__snapshots__/ipc-option.test.js.snap.webpack4 index ffb1b9a9ce..2697c355bc 100644 --- a/test/cli/__snapshots__/ipc-option.test.js.snap.webpack4 +++ b/test/cli/__snapshots__/ipc-option.test.js.snap.webpack4 @@ -1,11 +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] 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] 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 index ffb1b9a9ce..2697c355bc 100644 --- a/test/cli/__snapshots__/ipc-option.test.js.snap.webpack5 +++ b/test/cli/__snapshots__/ipc-option.test.js.snap.webpack5 @@ -1,11 +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] 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] 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/ipc-option.test.js b/test/cli/ipc-option.test.js index 2a20c6aebb..fdb5cd14cb 100644 --- a/test/cli/ipc-option.test.js +++ b/test/cli/ipc-option.test.js @@ -14,8 +14,7 @@ describe('"ipc" CLI option', () => { it('should work using "--ipc="', async () => { const isWindows = process.platform === 'win32'; - const localRelative = path.relative(process.cwd(), `${os.tmpdir()}/`); - const pipePrefix = isWindows ? '\\\\.\\pipe\\' : localRelative; + const pipePrefix = isWindows ? '\\\\.\\pipe\\' : os.tmpdir(); const pipeName = `webpack-dev-server.cli.sock`; const ipc = path.join(pipePrefix, pipeName); diff --git a/test/e2e/__snapshots__/ipc.test.js.snap.webpack4 b/test/e2e/__snapshots__/ipc.test.js.snap.webpack4 index aa90485da8..e31bdaa38e 100644 --- a/test/e2e/__snapshots__/ipc.test.js.snap.webpack4 +++ b/test/e2e/__snapshots__/ipc.test.js.snap.webpack4 @@ -21,3 +21,25 @@ Array [ `; 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 index aa90485da8..e31bdaa38e 100644 --- a/test/e2e/__snapshots__/ipc.test.js.snap.webpack5 +++ b/test/e2e/__snapshots__/ipc.test.js.snap.webpack5 @@ -21,3 +21,25 @@ Array [ `; 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 index 8ca61ed6d4..d0f48c69d7 100644 --- a/test/e2e/ipc.test.js +++ b/test/e2e/ipc.test.js @@ -33,7 +33,7 @@ describe('web socket server URL', () => { // Avoid racing between CLI test and this test server.options.ipc = server.options.ipc.replace( /webpack-dev-server/, - `webpack-dev-server.${process.pid}-1` + `webpack-dev-server.${process.pid}-0` ); await new Promise((resolve, reject) => { @@ -131,7 +131,7 @@ describe('web socket server URL', () => { }); }); - it.only(`should work with the "ipc" option using "string" value ("${webSocketServer}")`, async () => { + 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`; diff --git a/test/helpers/test-bin.js b/test/helpers/test-bin.js index 2a0e0aacd8..cdd16a3cdc 100644 --- a/test/helpers/test-bin.js +++ b/test/helpers/test-bin.js @@ -45,17 +45,10 @@ const testBin = (testArgs, configPath) => { const normalizeStderr = (stderr, options = {}) => { let normalizedStderr = stripAnsi(stderr); - const isWindows = process.platform === 'win32'; - const localRelative = path.relative(process.cwd(), `${os.tmpdir()}/`); - const pipeRoot = isWindows ? '\\\\.\\pipe\\' : localRelative; - normalizedStderr = normalizedStderr .replace(/\\/g, '/') .replace(new RegExp(process.cwd().replace(/\\/g, '/'), 'g'), '') - .replace( - new RegExp(pipeRoot.replace(/\\/g, '/'), 'g'), - `${isWindows ? '/' : ''}` - ); + .replace(new RegExp(os.tmpdir().replace(/\\/g, '/'), 'g'), ''); const networkIPv4 = internalIp.v4.sync(); From 4d1ed7a2f76e20e0c1b52070281d904fe12ca75e Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Fri, 25 Jun 2021 19:06:43 +0300 Subject: [PATCH 25/31] test: timeout --- setupTest.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setupTest.js b/setupTest.js index ee41cc92d0..978e5c3c91 100644 --- a/setupTest.js +++ b/setupTest.js @@ -2,4 +2,4 @@ process.env.CHOKIDAR_USEPOLLING = true; -jest.setTimeout(90000); +jest.setTimeout(120000); From 50548e397c9e6b9ca13cc98b6d0171c02920429f Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Fri, 25 Jun 2021 19:20:00 +0300 Subject: [PATCH 26/31] test: timeout --- setupTest.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setupTest.js b/setupTest.js index 978e5c3c91..bb885657ac 100644 --- a/setupTest.js +++ b/setupTest.js @@ -2,4 +2,4 @@ process.env.CHOKIDAR_USEPOLLING = true; -jest.setTimeout(120000); +jest.setTimeout(140000); From 7dc85f435320c0eaa82fa4bf2ce51adc22367363 Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Fri, 25 Jun 2021 19:36:52 +0300 Subject: [PATCH 27/31] test: fix --- test/server/watchFiles-option.test.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/test/server/watchFiles-option.test.js b/test/server/watchFiles-option.test.js index 0f3c71388c..2340f7fa8d 100644 --- a/test/server/watchFiles-option.test.js +++ b/test/server/watchFiles-option.test.js @@ -173,6 +173,8 @@ describe("'watchFiles' option", () => { const nonExistFile = path.join(watchDir, 'assets/non-exist.txt'); beforeAll(async () => { + fs.unlinkSync(nonExistFile); + const compiler = webpack(config); server = new Server( @@ -213,9 +215,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); }); }); From 73dc4cc30cdc74df2e41b8907e5e293c12a2dcfb Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Fri, 25 Jun 2021 19:49:39 +0300 Subject: [PATCH 28/31] test: fix --- test/server/watchFiles-option.test.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/server/watchFiles-option.test.js b/test/server/watchFiles-option.test.js index 2340f7fa8d..aac4046b6d 100644 --- a/test/server/watchFiles-option.test.js +++ b/test/server/watchFiles-option.test.js @@ -173,7 +173,11 @@ describe("'watchFiles' option", () => { const nonExistFile = path.join(watchDir, 'assets/non-exist.txt'); beforeAll(async () => { - fs.unlinkSync(nonExistFile); + try { + fs.unlinkSync(nonExistFile); + } catch (error) { + // ignore + } const compiler = webpack(config); From a9972bff45bb1dc0d62176bdb79fe172f63dca32 Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Fri, 25 Jun 2021 20:18:29 +0300 Subject: [PATCH 29/31] test: fix --- test/helpers/test-bin.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/helpers/test-bin.js b/test/helpers/test-bin.js index cdd16a3cdc..73c32e7d7c 100644 --- a/test/helpers/test-bin.js +++ b/test/helpers/test-bin.js @@ -48,7 +48,8 @@ const normalizeStderr = (stderr, options = {}) => { normalizedStderr = normalizedStderr .replace(/\\/g, '/') .replace(new RegExp(process.cwd().replace(/\\/g, '/'), 'g'), '') - .replace(new RegExp(os.tmpdir().replace(/\\/g, '/'), 'g'), ''); + .replace(new RegExp(os.tmpdir().replace(/\\/g, '/'), 'g'), '') + .replace(new RegExp('\\\\.\\pipe'.replace(/\\/g, '/'), 'g'), ''); const networkIPv4 = internalIp.v4.sync(); From 9e96927c5c75126babf7468c62429faf946afc06 Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Fri, 25 Jun 2021 20:44:20 +0300 Subject: [PATCH 30/31] test: fix --- .../utils/__snapshots__/normalizeOptions.test.js.snap.webpack4 | 2 +- .../utils/__snapshots__/normalizeOptions.test.js.snap.webpack5 | 2 +- test/server/utils/normalizeOptions.test.js | 2 +- test/validate-options.test.js | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) 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/validate-options.test.js b/test/validate-options.test.js index 686b7e06f5..7b50e0248e 100644 --- a/test/validate-options.test.js +++ b/test/validate-options.test.js @@ -274,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: { From 1eac0f932efde32fa1d1be92f8d95dc3f99c512c Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Fri, 25 Jun 2021 21:38:50 +0300 Subject: [PATCH 31/31] test: fix --- test/cli/allowedHosts-option.test.js | 24 +++- test/cli/basic.test.js | 56 ++++++--- test/cli/bonjour-option.test.js | 16 ++- test/cli/client-option.test.js | 85 +++++++++++-- test/cli/colors.test.js | 27 ++++- test/cli/compress-option.test.js | 5 +- test/cli/historyApiFallback-option.test.js | 13 +- test/cli/host-option.test.js | 66 ++++++++-- test/cli/hot-option.test.js | 17 ++- test/cli/http2-option.test.js | 5 +- test/cli/https-option.test.js | 32 +++-- test/cli/liveReload-option.test.js | 5 +- test/cli/open-option.test.js | 133 ++++++++++++++++----- test/cli/static-option.test.js | 89 ++++++++++---- test/cli/watchFiles-option.test.js | 7 ++ test/cli/webSocketServer-option.test.js | 15 ++- test/ports-map.js | 15 +++ 17 files changed, 494 insertions(+), 116 deletions(-) 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/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/ports-map.js b/test/ports-map.js index f02bc85349..d7534ede1e 100644 --- a/test/ports-map.js +++ b/test/ports-map.js @@ -49,6 +49,21 @@ const listOfTests = { '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;