diff --git a/bin/cli-flags.js b/bin/cli-flags.js index b2a71e92b8..8d3044cbee 100644 --- a/bin/cli-flags.js +++ b/bin/cli-flags.js @@ -275,6 +275,36 @@ module.exports = { multiple: false, simpleType: 'string', }, + 'client-web-socket-url-username': { + configs: [ + { + type: 'string', + multiple: false, + description: + 'Tells clients connected to devServer to use the provided username to authenticate.', + path: 'client.webSocketURL.username', + }, + ], + description: + 'Tells clients connected to devServer to use the provided username to authenticate.', + simpleType: 'string', + multiple: false, + }, + 'client-web-socket-url-password': { + configs: [ + { + type: 'string', + multiple: false, + description: + 'Tells clients connected to devServer to use the provided password to authenticate.', + path: 'client.webSocketURL.password', + }, + ], + description: + 'Tells clients connected to devServer to use the provided password to authenticate.', + simpleType: 'string', + multiple: false, + }, 'web-socket-server': { configs: [ { diff --git a/lib/options.json b/lib/options.json index 52cd0e9eba..12076138db 100644 --- a/lib/options.json +++ b/lib/options.json @@ -154,6 +154,10 @@ "description": "Tells clients connected to devServer to use the provided path to connect.", "type": "string" }, + "password": { + "description": "Tells clients connected to devServer to use the provided password to authenticate.", + "type": "string" + }, "port": { "description": "Tells clients connected to devServer to use the provided port.", "anyOf": [ @@ -177,6 +181,10 @@ "minLength": 1 } ] + }, + "username": { + "description": "Tells clients connected to devServer to use the provided username to authenticate.", + "type": "string" } } } diff --git a/lib/utils/DevServerPlugin.js b/lib/utils/DevServerPlugin.js index 26e0181a74..12e5f21e3c 100644 --- a/lib/utils/DevServerPlugin.js +++ b/lib/utils/DevServerPlugin.js @@ -93,6 +93,7 @@ class DevServerPlugin { if (typeof options.client.webSocketURL.path !== 'undefined') { path = options.client.webSocketURL.path; } + // Web socket server works on custom `path` else if ( typeof options.webSocketServer.options.prefix !== 'undefined' || @@ -103,24 +104,35 @@ class DevServerPlugin { options.webSocketServer.options.path; } - /** @type {Record} */ - const searchParams = {}; + /** @type {string} */ + let username = ''; + + if (typeof options.client.webSocketURL.username !== 'undefined') { + username = options.client.webSocketURL.username; + } + + /** @type {string} */ + let password = ''; + + if (typeof options.client.webSocketURL.password !== 'undefined') { + password = options.client.webSocketURL.password; + } + + const searchParams = new URLSearchParams(); if (typeof options.client.logging !== 'undefined') { - searchParams.logging = options.client.logging; + searchParams.set('logging', options.client.logging); } + const searchParamsString = searchParams.toString(); + return encodeURIComponent( new URL( - `${protocol}//${ipaddr.IPv6.isIPv6(host) ? `[${host}]` : host}${ + `${protocol}//${username}${password ? `:${password}` : ''}${ + username || password ? `@` : '' + }${ipaddr.IPv6.isIPv6(host) ? `[${host}]` : host}${ port ? `:${port}` : '' - }${path || '/'}${ - Object.keys(searchParams).length > 0 - ? `?${Object.entries(searchParams) - .map(([key, value]) => `${key}=${value}`) - .join('&')}` - : '' - }` + }${path || '/'}${searchParamsString ? `?${searchParamsString}` : ''}` ).toString() ).replace( /[!'()*]/g, diff --git a/lib/utils/normalizeOptions.js b/lib/utils/normalizeOptions.js index abcc5f40c8..50dc9121dc 100644 --- a/lib/utils/normalizeOptions.js +++ b/lib/utils/normalizeOptions.js @@ -124,6 +124,8 @@ function normalizeOptions(compiler, options, logger) { host: parsedURL.hostname, port: parsedURL.port.length > 0 ? Number(parsedURL.port) : '', path: parsedURL.pathname, + username: parsedURL.username, + password: parsedURL.password, }; } else if (typeof options.client.webSocketURL.port === 'string') { options.client.webSocketURL.port = Number(options.client.webSocketURL.port); diff --git a/test/__snapshots__/validate-options.test.js.snap.webpack4 b/test/__snapshots__/validate-options.test.js.snap.webpack4 index ef404505a2..ed0aa8280f 100644 --- a/test/__snapshots__/validate-options.test.js.snap.webpack4 +++ b/test/__snapshots__/validate-options.test.js.snap.webpack4 @@ -172,7 +172,7 @@ exports[`options validate should throw an error on the "client" option with '{"w exports[`options validate should throw an error on the "client" option with '{"webSocketURL":{"port":true}}' value 1`] = ` "ValidationError: Invalid options object. Dev Server has been initialized using an options object that does not match the API schema. - options.client.webSocketURL should be one of these: - non-empty string | object { host?, path?, port?, protocol? } + non-empty string | object { host?, path?, password?, port?, protocol?, username? } -> Allows to specify URL to web socket server (useful when you're proxying dev server and client script does not always know where to connect to). Details: * options.client.webSocketURL.port should be one of these: @@ -183,6 +183,18 @@ exports[`options validate should throw an error on the "client" option with '{"w * options.client.webSocketURL.port should be a non-empty string." `; +exports[`options validate should throw an error on the "client" option with '{"webSocketURL":{"username":123,"password":976}}' value 1`] = ` +"ValidationError: Invalid options object. Dev Server has been initialized using an options object that does not match the API schema. + - options.client.webSocketURL should be one of these: + non-empty string | object { host?, path?, password?, port?, protocol?, username? } + -> Allows to specify URL to web socket server (useful when you're proxying dev server and client script does not always know where to connect to). + Details: + * options.client.webSocketURL.password should be a string. + -> Tells clients connected to devServer to use the provided password to authenticate. + * options.client.webSocketURL.username should be a string. + -> Tells clients connected to devServer to use the provided username to authenticate." +`; + exports[`options validate should throw an error on the "client" option with 'whoops!' value 1`] = ` "ValidationError: Invalid options object. Dev Server has been initialized using an options object that does not match the API schema. - options.client should be an object: diff --git a/test/__snapshots__/validate-options.test.js.snap.webpack5 b/test/__snapshots__/validate-options.test.js.snap.webpack5 index ef404505a2..ed0aa8280f 100644 --- a/test/__snapshots__/validate-options.test.js.snap.webpack5 +++ b/test/__snapshots__/validate-options.test.js.snap.webpack5 @@ -172,7 +172,7 @@ exports[`options validate should throw an error on the "client" option with '{"w exports[`options validate should throw an error on the "client" option with '{"webSocketURL":{"port":true}}' value 1`] = ` "ValidationError: Invalid options object. Dev Server has been initialized using an options object that does not match the API schema. - options.client.webSocketURL should be one of these: - non-empty string | object { host?, path?, port?, protocol? } + non-empty string | object { host?, path?, password?, port?, protocol?, username? } -> Allows to specify URL to web socket server (useful when you're proxying dev server and client script does not always know where to connect to). Details: * options.client.webSocketURL.port should be one of these: @@ -183,6 +183,18 @@ exports[`options validate should throw an error on the "client" option with '{"w * options.client.webSocketURL.port should be a non-empty string." `; +exports[`options validate should throw an error on the "client" option with '{"webSocketURL":{"username":123,"password":976}}' value 1`] = ` +"ValidationError: Invalid options object. Dev Server has been initialized using an options object that does not match the API schema. + - options.client.webSocketURL should be one of these: + non-empty string | object { host?, path?, password?, port?, protocol?, username? } + -> Allows to specify URL to web socket server (useful when you're proxying dev server and client script does not always know where to connect to). + Details: + * options.client.webSocketURL.password should be a string. + -> Tells clients connected to devServer to use the provided password to authenticate. + * options.client.webSocketURL.username should be a string. + -> Tells clients connected to devServer to use the provided username to authenticate." +`; + exports[`options validate should throw an error on the "client" option with 'whoops!' value 1`] = ` "ValidationError: Invalid options object. Dev Server has been initialized using an options object that does not match the API schema. - options.client should be an object: diff --git a/test/cli/__snapshots__/cli.test.js.snap.webpack4 b/test/cli/__snapshots__/cli.test.js.snap.webpack4 index d9e3274eaf..35b7f2675a 100644 --- a/test/cli/__snapshots__/cli.test.js.snap.webpack4 +++ b/test/cli/__snapshots__/cli.test.js.snap.webpack4 @@ -73,6 +73,8 @@ Options: --client-web-socket-url-port Tells clients connected to devServer to use the provided port. --client-web-socket-url-path Tells clients connected to devServer to use the provided path to connect. --client-web-socket-url-protocol Tells clients connected to devServer to use the provided protocol. + --client-web-socket-url-username Tells clients connected to devServer to use the provided username to authenticate. + --client-web-socket-url-password Tells clients connected to devServer to use the provided password to authenticate. --web-socket-server Allows to set web socket server and options (by default 'ws'). https://webpack.js.org/configuration/dev-server/#devserverwebsocketserver --compress Enables gzip compression for everything served. https://webpack.js.org/configuration/dev-server/#devservercompress --no-compress Disables gzip compression for everything served. diff --git a/test/cli/__snapshots__/cli.test.js.snap.webpack5 b/test/cli/__snapshots__/cli.test.js.snap.webpack5 index a1428f6c9c..46dfae8119 100644 --- a/test/cli/__snapshots__/cli.test.js.snap.webpack5 +++ b/test/cli/__snapshots__/cli.test.js.snap.webpack5 @@ -72,8 +72,10 @@ Options: --client-web-socket-url Allows to specify URL to web socket server (useful when you're proxying dev server and client script does not always know where to connect to). --client-web-socket-url-host Tells clients connected to devServer to use the provided host. --client-web-socket-url-path Tells clients connected to devServer to use the provided path to connect. + --client-web-socket-url-password Tells clients connected to devServer to use the provided password to authenticate. --client-web-socket-url-port Tells clients connected to devServer to use the provided port. --client-web-socket-url-protocol Tells clients connected to devServer to use the provided protocol. + --client-web-socket-url-username Tells clients connected to devServer to use the provided username to authenticate. --compress Enables gzip compression for everything served. https://webpack.js.org/configuration/dev-server/#devservercompress --no-compress Negative 'compress' option. --history-api-fallback Allows to proxy requests through a specified index page (by default 'index.html'), useful for Single Page Applications that utilise the HTML5 History API. https://webpack.js.org/configuration/dev-server/#devserverhistoryapifallback diff --git a/test/e2e/__snapshots__/web-socket-server-url.test.js.snap.webpack4 b/test/e2e/__snapshots__/web-socket-server-url.test.js.snap.webpack4 index 3fa7d6ecd7..dfcf94d80b 100644 --- a/test/e2e/__snapshots__/web-socket-server-url.test.js.snap.webpack4 +++ b/test/e2e/__snapshots__/web-socket-server-url.test.js.snap.webpack4 @@ -261,6 +261,28 @@ Array [ exports[`web socket server URL should work with the "client.webSocketURL.host" option using "0.0.0.0" value ("ws"): page errors 1`] = `Array []`; +exports[`web socket server URL should work with the "client.webSocketURL.password" option ("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 "client.webSocketURL.password" option ("sockjs"): page errors 1`] = `Array []`; + +exports[`web socket server URL should work with the "client.webSocketURL.password" option ("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 "client.webSocketURL.password" option ("ws"): page errors 1`] = `Array []`; + exports[`web socket server URL should work with the "client.webSocketURL.path" option ("sockjs"): console messages 1`] = ` Array [ "[HMR] Waiting for update signal from WDS...", @@ -436,3 +458,47 @@ Array [ `; exports[`web socket server URL should work with the "client.webSocketURL.protocol" option using "http:" value and covert to "ws:" ("ws"): page errors 1`] = `Array []`; + +exports[`web socket server URL should work with the "client.webSocketURL.username" and "client.webSocketURL.password" option ("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 "client.webSocketURL.username" and "client.webSocketURL.password" option ("sockjs"): page errors 1`] = `Array []`; + +exports[`web socket server URL should work with the "client.webSocketURL.username" and "client.webSocketURL.password" option ("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 "client.webSocketURL.username" and "client.webSocketURL.password" option ("ws"): page errors 1`] = `Array []`; + +exports[`web socket server URL should work with the "client.webSocketURL.username" option ("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 "client.webSocketURL.username" option ("sockjs"): page errors 1`] = `Array []`; + +exports[`web socket server URL should work with the "client.webSocketURL.username" option ("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 "client.webSocketURL.username" option ("ws"): page errors 1`] = `Array []`; diff --git a/test/e2e/__snapshots__/web-socket-server-url.test.js.snap.webpack5 b/test/e2e/__snapshots__/web-socket-server-url.test.js.snap.webpack5 index 3fa7d6ecd7..dfcf94d80b 100644 --- a/test/e2e/__snapshots__/web-socket-server-url.test.js.snap.webpack5 +++ b/test/e2e/__snapshots__/web-socket-server-url.test.js.snap.webpack5 @@ -261,6 +261,28 @@ Array [ exports[`web socket server URL should work with the "client.webSocketURL.host" option using "0.0.0.0" value ("ws"): page errors 1`] = `Array []`; +exports[`web socket server URL should work with the "client.webSocketURL.password" option ("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 "client.webSocketURL.password" option ("sockjs"): page errors 1`] = `Array []`; + +exports[`web socket server URL should work with the "client.webSocketURL.password" option ("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 "client.webSocketURL.password" option ("ws"): page errors 1`] = `Array []`; + exports[`web socket server URL should work with the "client.webSocketURL.path" option ("sockjs"): console messages 1`] = ` Array [ "[HMR] Waiting for update signal from WDS...", @@ -436,3 +458,47 @@ Array [ `; exports[`web socket server URL should work with the "client.webSocketURL.protocol" option using "http:" value and covert to "ws:" ("ws"): page errors 1`] = `Array []`; + +exports[`web socket server URL should work with the "client.webSocketURL.username" and "client.webSocketURL.password" option ("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 "client.webSocketURL.username" and "client.webSocketURL.password" option ("sockjs"): page errors 1`] = `Array []`; + +exports[`web socket server URL should work with the "client.webSocketURL.username" and "client.webSocketURL.password" option ("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 "client.webSocketURL.username" and "client.webSocketURL.password" option ("ws"): page errors 1`] = `Array []`; + +exports[`web socket server URL should work with the "client.webSocketURL.username" option ("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 "client.webSocketURL.username" option ("sockjs"): page errors 1`] = `Array []`; + +exports[`web socket server URL should work with the "client.webSocketURL.username" option ("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 "client.webSocketURL.username" option ("ws"): page errors 1`] = `Array []`; diff --git a/test/e2e/web-socket-server-url.test.js b/test/e2e/web-socket-server-url.test.js index e7165d9ab0..84ba55ab17 100644 --- a/test/e2e/web-socket-server-url.test.js +++ b/test/e2e/web-socket-server-url.test.js @@ -7,7 +7,8 @@ const { createProxyMiddleware } = require('http-proxy-middleware'); const Server = require('../../lib/Server'); const config = require('../fixtures/client-config/webpack.config'); const runBrowser = require('../helpers/run-browser'); -const [port1, port2, port3, port4] = require('../ports-map').ClientOptions; +const [port1, port2, port3, port4, port5] = + require('../ports-map').ClientOptions; const webSocketServers = ['ws', 'sockjs']; @@ -1187,6 +1188,262 @@ describe('web socket server URL', () => { }); }); + it(`should work with the "client.webSocketURL.username" option ("${webSocketServer}")`, async () => { + const compiler = webpack(config); + const devServerOptions = { + client: { + webSocketURL: { + username: 'zenitsu', + }, + }, + webSocketServer, + port: port5, + host: '0.0.0.0', + allowedHosts: 'all', + }; + const server = new Server(devServerOptions, compiler); + + await new Promise((resolve, reject) => { + server.listen(devServerOptions.port, devServerOptions.host, (error) => { + if (error) { + reject(error); + + return; + } + + resolve(); + }); + }); + + 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://127.0.0.1:${port5}/main`, { + waitUntil: 'networkidle0', + }); + + const webSocketRequest = webSocketRequests[0]; + + expect(webSocketRequest.url).toContain( + `${websocketURLProtocol}://zenitsu@127.0.0.1:${port5}/ws` + ); + expect(consoleMessages.map((message) => message.text())).toMatchSnapshot( + 'console messages' + ); + expect(pageErrors).toMatchSnapshot('page errors'); + + await browser.close(); + await new Promise((resolve, reject) => { + server.close((error) => { + if (error) { + reject(error); + + return; + } + + resolve(); + }); + }); + }); + + it(`should work with the "client.webSocketURL.password" option ("${webSocketServer}")`, async () => { + const compiler = webpack(config); + const devServerOptions = { + client: { + webSocketURL: { + password: 'chuntaro', + }, + }, + webSocketServer, + port: port5, + host: '0.0.0.0', + allowedHosts: 'all', + }; + const server = new Server(devServerOptions, compiler); + + await new Promise((resolve, reject) => { + server.listen(devServerOptions.port, devServerOptions.host, (error) => { + if (error) { + reject(error); + + return; + } + + resolve(); + }); + }); + + 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://127.0.0.1:${port5}/main`, { + waitUntil: 'networkidle0', + }); + + const webSocketRequest = webSocketRequests[0]; + + expect(webSocketRequest.url).toContain( + // "sockjs" has bug with parsing URL + webSocketServer === 'ws' + ? `${websocketURLProtocol}://:chuntaro@127.0.0.1:${port5}/ws` + : `${websocketURLProtocol}://127.0.0.1:${port5}/ws` + ); + expect(consoleMessages.map((message) => message.text())).toMatchSnapshot( + 'console messages' + ); + expect(pageErrors).toMatchSnapshot('page errors'); + + await browser.close(); + await new Promise((resolve, reject) => { + server.close((error) => { + if (error) { + reject(error); + + return; + } + + resolve(); + }); + }); + }); + + it(`should work with the "client.webSocketURL.username" and "client.webSocketURL.password" option ("${webSocketServer}")`, async () => { + const compiler = webpack(config); + const devServerOptions = { + client: { + webSocketURL: { + username: 'zenitsu', + password: 'chuntaro', + }, + }, + webSocketServer, + port: port5, + host: '0.0.0.0', + allowedHosts: 'all', + }; + const server = new Server(devServerOptions, compiler); + + await new Promise((resolve, reject) => { + server.listen(devServerOptions.port, devServerOptions.host, (error) => { + if (error) { + reject(error); + + return; + } + + resolve(); + }); + }); + + 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://127.0.0.1:${port5}/main`, { + waitUntil: 'networkidle0', + }); + + const webSocketRequest = webSocketRequests[0]; + + expect(webSocketRequest.url).toContain( + `${websocketURLProtocol}://zenitsu:chuntaro@127.0.0.1:${port5}/ws` + ); + expect(consoleMessages.map((message) => message.text())).toMatchSnapshot( + 'console messages' + ); + expect(pageErrors).toMatchSnapshot('page errors'); + + await browser.close(); + await new Promise((resolve, reject) => { + server.close((error) => { + if (error) { + reject(error); + + return; + } + + resolve(); + }); + }); + }); + it(`should work with the "client.webSocketURL.path" option and custom web socket server "path" ("${webSocketServer}")`, async () => { const compiler = webpack(config); const devServerOptions = { diff --git a/test/ports-map.js b/test/ports-map.js index dbffb5b182..ddfe57e1f3 100644 --- a/test/ports-map.js +++ b/test/ports-map.js @@ -8,7 +8,7 @@ const portsList = { SockJSServer: 1, 'hot-and-live-reload': 1, Client: 1, - ClientOptions: 4, + ClientOptions: 5, logging: 1, overlay: 1, MultiCompiler: 1, diff --git a/test/server/__snapshots__/Server.test.js.snap.webpack4 b/test/server/__snapshots__/Server.test.js.snap.webpack4 index f2c83d038c..a0ee40d377 100644 --- a/test/server/__snapshots__/Server.test.js.snap.webpack4 +++ b/test/server/__snapshots__/Server.test.js.snap.webpack4 @@ -4,7 +4,7 @@ exports[`Server DevServerPlugin add hot option 1`] = ` Array [ Array [ "client", - "index.js?ws%3A%2F%2Flocalhost%3A8104%2Fws", + "index.js?ws%3A%2F%2Flocalhost%3A8105%2Fws", ], Array [ "node_modules", @@ -22,7 +22,7 @@ exports[`Server DevServerPlugin add hot-only option 1`] = ` Array [ Array [ "client", - "index.js?ws%3A%2F%2Flocalhost%3A8104%2Fws", + "index.js?ws%3A%2F%2Flocalhost%3A8105%2Fws", ], Array [ "node_modules", @@ -40,7 +40,7 @@ exports[`Server DevServerPlugin should create and run server with old parameters Array [ Array [ "client", - "index.js?ws%3A%2F%2Flocalhost%3A8104%2Fws", + "index.js?ws%3A%2F%2Flocalhost%3A8105%2Fws", ], Array [ "node_modules", diff --git a/test/server/__snapshots__/Server.test.js.snap.webpack5 b/test/server/__snapshots__/Server.test.js.snap.webpack5 index f2c83d038c..f0ce2c6599 100644 --- a/test/server/__snapshots__/Server.test.js.snap.webpack5 +++ b/test/server/__snapshots__/Server.test.js.snap.webpack5 @@ -4,7 +4,7 @@ exports[`Server DevServerPlugin add hot option 1`] = ` Array [ Array [ "client", - "index.js?ws%3A%2F%2Flocalhost%3A8104%2Fws", + "index.js?ws%3A%2F%2Flocalhost%3A8105%2Fws", ], Array [ "node_modules", @@ -22,7 +22,7 @@ exports[`Server DevServerPlugin add hot-only option 1`] = ` Array [ Array [ "client", - "index.js?ws%3A%2F%2Flocalhost%3A8104%2Fws", + "index.js?ws%3A%2F%2Flocalhost%3A8105%2Fws", ], Array [ "node_modules", @@ -40,7 +40,7 @@ exports[`Server DevServerPlugin should create and run server with old parameters Array [ Array [ "client", - "index.js?ws%3A%2F%2Flocalhost%3A8104%2Fws", + "index.js?ws%3A%2F%2Flocalhost%3A8105%2Fws", ], Array [ "node_modules", @@ -54,4 +54,4 @@ Array [ ] `; -exports[`Server getFreePort should throws the error when the port isn't found 1`] = `"busy"`; +exports[`Server getFreePort should throws the error when the port isn't found 1`] = `"listen EADDRINUSE: address already in use :::8080"`; diff --git a/test/server/servers/__snapshots__/WebsocketServer.test.js.snap.webpack4 b/test/server/servers/__snapshots__/WebsocketServer.test.js.snap.webpack4 index 16b78745af..64f2a65dc9 100644 --- a/test/server/servers/__snapshots__/WebsocketServer.test.js.snap.webpack4 +++ b/test/server/servers/__snapshots__/WebsocketServer.test.js.snap.webpack4 @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`WebsocketServer should receive connection, send message, and close client 1`] = `"localhost:8130"`; +exports[`WebsocketServer should receive connection, send message, and close client 1`] = `"localhost:8131"`; exports[`WebsocketServer should receive connection, send message, and close client 2`] = ` Array [ diff --git a/test/server/servers/__snapshots__/WebsocketServer.test.js.snap.webpack5 b/test/server/servers/__snapshots__/WebsocketServer.test.js.snap.webpack5 index 16b78745af..64f2a65dc9 100644 --- a/test/server/servers/__snapshots__/WebsocketServer.test.js.snap.webpack5 +++ b/test/server/servers/__snapshots__/WebsocketServer.test.js.snap.webpack5 @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`WebsocketServer should receive connection, send message, and close client 1`] = `"localhost:8130"`; +exports[`WebsocketServer should receive connection, send message, and close client 1`] = `"localhost:8131"`; exports[`WebsocketServer should receive connection, send message, and close client 2`] = ` Array [ diff --git a/test/server/utils/__snapshots__/normalizeOptions.test.js.snap.webpack4 b/test/server/utils/__snapshots__/normalizeOptions.test.js.snap.webpack4 index 91a974cfcd..a4f16ef6e4 100644 --- a/test/server/utils/__snapshots__/normalizeOptions.test.js.snap.webpack4 +++ b/test/server/utils/__snapshots__/normalizeOptions.test.js.snap.webpack4 @@ -1418,6 +1418,44 @@ Object { } `; +exports[`normalizeOptions username and password should set correct options 1`] = ` +Object { + "allowedHosts": "auto", + "client": Object { + "hotEntry": true, + "overlay": true, + "webSocketURL": Object { + "password": "chuntaro", + "username": "zenitsu", + }, + }, + "compress": true, + "devMiddleware": Object {}, + "hot": true, + "liveReload": true, + "setupExitSignals": true, + "static": Array [ + Object { + "directory": "CWD", + "publicPath": Array [ + "/", + ], + "serveIndex": Object { + "icons": true, + }, + "staticOptions": Object {}, + "watch": Object {}, + }, + ], + "webSocketServer": Object { + "options": Object { + "path": "/ws", + }, + "type": "ws", + }, +} +`; + exports[`normalizeOptions webSocketServer custom server class should set correct options 1`] = ` Object { "allowedHosts": "auto", diff --git a/test/server/utils/__snapshots__/normalizeOptions.test.js.snap.webpack5 b/test/server/utils/__snapshots__/normalizeOptions.test.js.snap.webpack5 index 91a974cfcd..a4f16ef6e4 100644 --- a/test/server/utils/__snapshots__/normalizeOptions.test.js.snap.webpack5 +++ b/test/server/utils/__snapshots__/normalizeOptions.test.js.snap.webpack5 @@ -1418,6 +1418,44 @@ Object { } `; +exports[`normalizeOptions username and password should set correct options 1`] = ` +Object { + "allowedHosts": "auto", + "client": Object { + "hotEntry": true, + "overlay": true, + "webSocketURL": Object { + "password": "chuntaro", + "username": "zenitsu", + }, + }, + "compress": true, + "devMiddleware": Object {}, + "hot": true, + "liveReload": true, + "setupExitSignals": true, + "static": Array [ + Object { + "directory": "CWD", + "publicPath": Array [ + "/", + ], + "serveIndex": Object { + "icons": true, + }, + "staticOptions": Object {}, + "watch": Object {}, + }, + ], + "webSocketServer": Object { + "options": Object { + "path": "/ws", + }, + "type": "ws", + }, +} +`; + exports[`normalizeOptions webSocketServer custom server class should set correct options 1`] = ` Object { "allowedHosts": "auto", diff --git a/test/server/utils/normalizeOptions.test.js b/test/server/utils/normalizeOptions.test.js index 28518a448f..a922ef5968 100644 --- a/test/server/utils/normalizeOptions.test.js +++ b/test/server/utils/normalizeOptions.test.js @@ -152,6 +152,19 @@ describe('normalizeOptions', () => { }, optionsResults: null, }, + { + title: 'username and password', + multiCompiler: false, + options: { + client: { + webSocketURL: { + username: 'zenitsu', + password: 'chuntaro', + }, + }, + }, + optionsResults: null, + }, { title: 'client path without leading/ending slashes', multiCompiler: false, diff --git a/test/validate-options.test.js b/test/validate-options.test.js index 9533c29976..e256bb4f4e 100644 --- a/test/validate-options.test.js +++ b/test/validate-options.test.js @@ -98,6 +98,9 @@ const tests = { { webSocketURL: { host: 'localhost', port: 8080, path: '/my-path/' }, }, + { + webSocketURL: { username: 'zoro', password: 'roronoa' }, + }, ], failure: [ 'whoops!', @@ -155,6 +158,9 @@ const tests = { { webSocketURL: { port: '' }, }, + { + webSocketURL: { username: 123, password: 976 }, + }, ], }, compress: {