diff --git a/bin/cli-flags.js b/bin/cli-flags.js index 36986734b9..c500b9524b 100644 --- a/bin/cli-flags.js +++ b/bin/cli-flags.js @@ -394,16 +394,6 @@ module.exports = { negatedDescription: 'Disable gzip compression.', negative: true, }, - { - name: 'public', - type: String, - configs: [ - { - type: 'string', - }, - ], - description: 'The public hostname/ip address of the server.', - }, { name: 'firewall', type: [Boolean, String], diff --git a/client-src/utils/createSocketURL.js b/client-src/utils/createSocketURL.js index 40e8cc4970..67c5cabf16 100644 --- a/client-src/utils/createSocketURL.js +++ b/client-src/utils/createSocketURL.js @@ -7,14 +7,6 @@ const url = require('url'); function createSocketURL(parsedURL) { let { auth, hostname, protocol, port } = parsedURL; - const getURLSearchParam = (name) => { - if (parsedURL.searchParams) { - return parsedURL.searchParams.get(name); - } - - return parsedURL.query && parsedURL.query[name]; - }; - // Node.js module parses it as `::` // `new URL(urlString, [baseURLstring])` parses it as '[::]' const isInAddrAny = @@ -66,22 +58,25 @@ function createSocketURL(parsedURL) { // // All of these sock url params are optionally passed in through resourceQuery, // so we need to fall back to the default if they are not provided - const socketURLHostname = ( - getURLSearchParam('host') || - hostname || - 'localhost' - ).replace(/^\[(.*)\]$/, '$1'); + const socketURLHostname = (hostname || 'localhost').replace( + /^\[(.*)\]$/, + '$1' + ); if (!port || port === '0') { port = self.location.port; } - const socketURLPort = getURLSearchParam('port') || port; + const socketURLPort = port; // If path is provided it'll be passed in via the resourceQuery as a // query param so it has to be parsed out of the querystring in order for the // client to open the socket to the correct location. - const socketURLPathname = getURLSearchParam('path') || '/ws'; + let socketURLPathname = '/ws'; + + if (parsedURL.pathname && !parsedURL.fromCurrentScript) { + socketURLPathname = parsedURL.pathname; + } return url.format({ protocol: socketURLProtocol, diff --git a/client-src/utils/parseURL.js b/client-src/utils/parseURL.js index da077db269..d40db3c2b1 100644 --- a/client-src/utils/parseURL.js +++ b/client-src/utils/parseURL.js @@ -8,13 +8,18 @@ function parseURL(resourceQuery) { if (typeof resourceQuery === 'string' && resourceQuery !== '') { // If this bundle is inlined, use the resource query to get the correct url. - // format is like `?http://0.0.0.0:8096&port=8097&host=localhost` + // for backward compatibility we supports: + // - ?ws://0.0.0.0:8096&3Flogging=info + // - ?ws%3A%2F%2F192.168.0.5%3A8080%2F%3Flogging%3Dinfo + // Also we support `http` and `https` for backward compatibility too options = url.parse( - resourceQuery - // strip leading `?` from query string to get a valid URL - .substr(1) - // replace first `&` with `?` to have a valid query string - .replace('&', '?'), + decodeURIComponent( + resourceQuery + // strip leading `?` from query string to get a valid URL + .substr(1) + // replace first `&` with `?` to have a valid query string + .replace('&', '?') + ), true ); } else { @@ -36,9 +41,11 @@ function parseURL(resourceQuery) { if (scriptSourceURL) { options = scriptSourceURL; + options.fromCurrentScript = true; } } else { options = url.parse(self.location.href, true, true); + options.fromCurrentScript = true; } } diff --git a/examples/cli/public-protocol/app.js b/examples/cli/public-protocol/app.js deleted file mode 100644 index d1a9c0496f..0000000000 --- a/examples/cli/public-protocol/app.js +++ /dev/null @@ -1,6 +0,0 @@ -'use strict'; - -const target = document.querySelector('#target'); - -target.innerHTML = - 'Please check the sockjs-info request in devtools, it should try to connect to the protocol + server defined in the public setting.'; diff --git a/examples/cli/public/README.md b/examples/cli/web-socket-url-cli/README.md similarity index 67% rename from examples/cli/public/README.md rename to examples/cli/web-socket-url-cli/README.md index f6f654bbe2..650fec3905 100644 --- a/examples/cli/public/README.md +++ b/examples/cli/web-socket-url-cli/README.md @@ -1,14 +1,14 @@ -# CLI: Public Option +# CLI: Web Socket URL ```console -npx webpack serve --open-target --host 0.0.0.0 --public :8080 +npx webpack serve --open-target --host 0.0.0.0 --web-socket-url :8080 ``` _NOTE: replace `` with your local IP Address._ In order to make the server publicly accessible the client needs to know with what host to connect to the server. If `--host 0.0.0.0` is given, the client -would try to connect to `0.0.0.0`. With the `--public` option it is possible to +would try to connect to `0.0.0.0`. With the `--web-socket-url` options it is possible to override this. ## What Should Happen @@ -18,4 +18,4 @@ override this. 3. Open the console in your browser's devtools. 4. Select the 'Network' tab. 5. Select the 'WS' or 'WebSockets' sub-tab. -6. Verify that the WebSocket is connecting to `:8080`. +6. Verify that the WebSocket is connecting to `:8080`. diff --git a/examples/cli/public/app.js b/examples/cli/web-socket-url-cli/app.js similarity index 100% rename from examples/cli/public/app.js rename to examples/cli/web-socket-url-cli/app.js diff --git a/examples/cli/public/webpack.config.js b/examples/cli/web-socket-url-cli/webpack.config.js similarity index 100% rename from examples/cli/public/webpack.config.js rename to examples/cli/web-socket-url-cli/webpack.config.js diff --git a/examples/cli/public-protocol/README.md b/examples/cli/web-socket-url/README.md similarity index 100% rename from examples/cli/public-protocol/README.md rename to examples/cli/web-socket-url/README.md diff --git a/examples/cli/web-socket-url/app.js b/examples/cli/web-socket-url/app.js new file mode 100644 index 0000000000..5184108804 --- /dev/null +++ b/examples/cli/web-socket-url/app.js @@ -0,0 +1,6 @@ +'use strict'; + +const target = document.querySelector('#target'); + +target.innerHTML = + 'Please check the ws request in devtools, it should try to connect to the protocol + server defined in the webSocketURL setting.'; diff --git a/examples/cli/public-protocol/index.html b/examples/cli/web-socket-url/index.html similarity index 100% rename from examples/cli/public-protocol/index.html rename to examples/cli/web-socket-url/index.html diff --git a/examples/cli/public-protocol/webpack.config.js b/examples/cli/web-socket-url/webpack.config.js similarity index 81% rename from examples/cli/public-protocol/webpack.config.js rename to examples/cli/web-socket-url/webpack.config.js index 9e557cd40a..7e519e2876 100644 --- a/examples/cli/public-protocol/webpack.config.js +++ b/examples/cli/web-socket-url/webpack.config.js @@ -9,7 +9,9 @@ module.exports = setup({ entry: './app.js', devServer: { host: '0.0.0.0', - public: 'https://localhost:8080', + client: { + webSocketURL: 'ws://localhost:8080', + }, firewall: false, }, }); diff --git a/lib/Server.js b/lib/Server.js index 43b88a71e1..a09f7ab94d 100644 --- a/lib/Server.js +++ b/lib/Server.js @@ -969,17 +969,9 @@ class Server { } } - // also allow public hostname if provided - if (typeof this.options.public === 'string') { - const idxPublic = this.options.public.indexOf(':'); - const publicHostname = - idxPublic >= 0 - ? this.options.public.substr(0, idxPublic) - : this.options.public; - - if (hostname === publicHostname) { - return true; - } + // Also allow if `client.webSocketURL.host` provided + if (typeof this.options.client.webSocketURL !== 'undefined') { + return this.options.client.webSocketURL.host === hostname; } // disallow diff --git a/lib/options.json b/lib/options.json index 655aabd0da..f8fb2eb120 100644 --- a/lib/options.json +++ b/lib/options.json @@ -229,28 +229,6 @@ ], "description": "Allows to set custom transport to communicate with server." }, - "host": { - "type": "string", - "description": "Tells clients connected to devServer to use the provided host." - }, - "path": { - "type": "string", - "description": "Tells clients connected to devServer to use the provided path to connect." - }, - "port": { - "anyOf": [ - { - "type": "number" - }, - { - "type": "string" - }, - { - "enum": ["auto"] - } - ], - "description": "Tells clients connected to devServer to use the provided port." - }, "logging": { "enum": ["none", "error", "warn", "info", "log", "verbose"], "decription": "Log level in the browser." @@ -301,6 +279,34 @@ } ], "description": "Tells devServer to inject a Hot Module Replacement entry." + }, + "webSocketURL": { + "anyOf": [ + { + "type": "string", + "minLength": 1 + }, + { + "type": "object", + "additionalProperties": false, + "properties": { + "host": { + "type": "string", + "minLength": 1, + "description": "Tells clients connected to devServer to use the provided host." + }, + "port": { + "type": "number", + "description": "Tells clients connected to devServer to use the provided port." + }, + "path": { + "type": "string", + "description": "Tells clients connected to devServer to use the provided path to connect." + } + } + } + ], + "description": "When using dev server and you're proxying dev-server, the client script does not always know where to connect to." } }, "description": "Specifies client properties. https://webpack.js.org/configuration/dev-server/#devserverclient", @@ -540,10 +546,6 @@ ], "description": "Proxying some URLs can be useful when you have a separate API backend development server and you want to send API requests on the same domain. https://webpack.js.org/configuration/dev-server/#devserverproxy" }, - "public": { - "type": "string", - "description": "When using dev server and you're proxying dev-server, the client script does not always know where to connect to. It will try to guess the URL of the server based on window.location, but if that fails you'll need to use this. https://webpack.js.org/configuration/dev-server/#devserverpublic" - }, "setupExitSignals": { "type": "boolean", "description": "It takes a boolean and if true (default on CLI), the server will close and exit the process on SIGINT and SIGTERM. https://webpack.js.org/configuration/dev-server/#devserversetupexitsignals" diff --git a/lib/utils/DevServerPlugin.js b/lib/utils/DevServerPlugin.js index e92c1ffda1..b57b132c04 100644 --- a/lib/utils/DevServerPlugin.js +++ b/lib/utils/DevServerPlugin.js @@ -1,7 +1,7 @@ 'use strict'; const webpack = require('webpack'); -const createDomain = require('./createDomain'); +const ipaddr = require('ipaddr.js'); const getSocketClientPath = require('./getSocketClientPath'); // @ts-ignore @@ -28,55 +28,108 @@ class DevServerPlugin { apply(compiler) { const { options } = this; + /** @type {"ws" | "wss"} */ + const protocol = options.https ? 'wss' : 'ws'; + /** @type {string} */ - const domain = createDomain(options); + let host; // SockJS is not supported server mode, so `host` and `port` can't specified, let's ignore them // TODO show warning about this const isSockJSType = options.webSocketServer.type === 'sockjs'; - /** @type {string} */ - let host = ''; - - if (options.client && options.client.host) { - host = `&host=${options.client.host}`; - } else if (options.webSocketServer.options.host && !isSockJSType) { - host = `&host=${options.webSocketServer.options.host}`; + // We are proxying dev server and need to specify custom `host` + if (typeof options.client.webSocketURL.host !== 'undefined') { + host = options.client.webSocketURL.host; + } + // Web socket server works on custom `host`, only for `ws` because `sock-js` is not support custom `host` + else if ( + typeof options.webSocketServer.options.host !== 'undefined' && + !isSockJSType + ) { + host = options.webSocketServer.options.host; + } + // The `host` option is specified + else if (typeof this.options.host !== 'undefined' && this.options.host) { + host = this.options.host; + } + // The `port` option is not specified + else { + host = '0.0.0.0'; } - /** @type {string} */ - let port = ''; - - if (options.client && options.client.port) { - port = `&port=${options.client.port}`; - } else if (options.webSocketServer.options.port && !isSockJSType) { - port = `&port=${options.webSocketServer.options.port}`; - } else if (options.port) { - port = `&port=${options.port}`; - } else { - port = ''; + /** @type {number | string} */ + let port; + + // We are proxying dev server and need to specify custom `port` + if (typeof options.client.webSocketURL.port !== 'undefined') { + port = options.client.webSocketURL.port; + } + // Web socket server works on custom `port`, only for `ws` because `sock-js` is not support custom `port` + else if ( + typeof options.webSocketServer.options.port !== 'undefined' && + !isSockJSType + ) { + port = options.webSocketServer.options.port; + } + // The `port` option is specified + else if (typeof options.port === 'number') { + port = options.port; + } + // The `port` option is specified using `string` + else if (typeof options.port === 'string' && options.port !== 'auto') { + port = Number(options.port); + } + // The `port` option is not specified or set to `auto` + else { + port = 0; } /** @type {string} */ let path = ''; - // Only add the path if it is not default - if (options.client && options.client.path && options.client.path) { - path = `&path=${options.client.path}`; - } else if (options.webSocketServer.options.path) { - path = `&path=${options.webSocketServer.options.path}`; + // We are proxying dev server and need to specify custom `path` + 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' || + typeof options.webSocketServer.options.path !== 'undefined' + ) { + path = + options.webSocketServer.options.prefix || + options.webSocketServer.options.path; } - /** @type {string} */ - const logging = - options.client && options.client.logging - ? `&logging=${options.client.logging}` - : ''; + /** @type {Record} */ + const searchParams = {}; + + if (typeof options.client.logging !== 'undefined') { + searchParams.logging = options.client.logging; + } + + const webSocketURL = encodeURIComponent( + new URL( + `${protocol}://${ipaddr.IPv6.isIPv6(host) ? `[${host}]` : host}${ + port ? `:${port}` : '' + }${path || '/'}${ + Object.keys(searchParams).length > 0 + ? `?${Object.entries(searchParams) + .map(([key, value]) => `${key}=${value}`) + .join('&')}` + : '' + }` + ).toString() + ).replace( + /[!'()*]/g, + (character) => `%${character.charCodeAt(0).toString(16)}` + ); /** @type {string} */ const clientEntry = `${require.resolve( '../../client/index.js' - )}?${domain}${host}${path}${port}${logging}`; + )}?${webSocketURL}`; /** @type {(string[] | string)} */ let hotEntry; @@ -117,11 +170,13 @@ class DevServerPlugin { // make sure that we do not add duplicates. /** @type {Entry} */ const entriesClone = additionalEntries.slice(0); + [].concat(originalEntry).forEach((newEntry) => { if (!entriesClone.includes(newEntry)) { entriesClone.push(newEntry); } }); + return entriesClone; }; diff --git a/lib/utils/createDomain.js b/lib/utils/createDomain.js deleted file mode 100644 index 58b6523e84..0000000000 --- a/lib/utils/createDomain.js +++ /dev/null @@ -1,31 +0,0 @@ -'use strict'; - -const url = require('url'); - -function createDomain(options, server) { - const protocol = options.https ? 'https' : 'http'; - // use location hostname and port by default in createSocketURL - // ipv6 detection is not required as 0.0.0.0 is just used as a placeholder - let hostname; - - if (server) { - hostname = server.address().address; - } else { - hostname = '0.0.0.0'; - } - - const port = server ? server.address().port : 0; - - // use explicitly defined public url - // (prefix with protocol if not explicitly given) - if (options.public) { - return /^[a-zA-Z]+:\/\//.test(options.public) - ? `${options.public}` - : `${protocol}://${options.public}`; - } - - // the formatted domain (url without path) of the webpack server - return url.format({ protocol, hostname, port }); -} - -module.exports = createDomain; diff --git a/lib/utils/normalizeOptions.js b/lib/utils/normalizeOptions.js index 26b92bef71..e6ef52c086 100644 --- a/lib/utils/normalizeOptions.js +++ b/lib/utils/normalizeOptions.js @@ -104,6 +104,18 @@ function normalizeOptions(compiler, options, logger) { options.client = {}; } + if (typeof options.client.webSocketURL === 'undefined') { + options.client.webSocketURL = {}; + } else if (typeof options.client.webSocketURL === 'string') { + const parsedURL = new URL(options.client.webSocketURL); + + options.client.webSocketURL = { + host: parsedURL.hostname, + port: parsedURL.port, + path: parsedURL.pathname, + }; + } + // Enable client overlay by default if (typeof options.client.overlay === 'undefined') { options.client.overlay = true; diff --git a/test/__snapshots__/validate-options.test.js.snap.webpack4 b/test/__snapshots__/validate-options.test.js.snap.webpack4 index 5580b1b45f..1aa6a376e2 100644 --- a/test/__snapshots__/validate-options.test.js.snap.webpack4 +++ b/test/__snapshots__/validate-options.test.js.snap.webpack4 @@ -12,12 +12,6 @@ exports[`options validate should throw an error on the "bonjour" option with '' -> Options for bonjour, description available at https://github.com/watson/bonjour#initializing" `; -exports[`options validate should throw an error on the "client" option with '{"host":true,"path":"","port":8080}' value 1`] = ` -"ValidationError: Invalid configuration object. Object has been initialized using a configuration object that does not match the API schema. - - configuration.client.host should be a string. - -> Tells clients connected to devServer to use the provided host." -`; - exports[`options validate should throw an error on the "client" option with '{"hotEntry":[""]}' value 1`] = ` "ValidationError: Invalid configuration object. Object has been initialized using a configuration object that does not match the API schema. - configuration.client.hotEntry should be one of these: @@ -73,23 +67,6 @@ exports[`options validate should throw an error on the "client" option with '{"o -> Show a full-screen overlay in the browser when there are compiler warnings." `; -exports[`options validate should throw an error on the "client" option with '{"path":true}' value 1`] = ` -"ValidationError: Invalid configuration object. Object has been initialized using a configuration object that does not match the API schema. - - configuration.client.path should be a string. - -> Tells clients connected to devServer to use the provided path to connect." -`; - -exports[`options validate should throw an error on the "client" option with '{"port":true}' value 1`] = ` -"ValidationError: Invalid configuration object. Object has been initialized using a configuration object that does not match the API schema. - - configuration.client.port should be one of these: - number | string | \\"auto\\" - -> Tells clients connected to devServer to use the provided port. - Details: - * configuration.client.port should be a number. - * configuration.client.port should be a string. - * configuration.client.port should be \\"auto\\"." -`; - exports[`options validate should throw an error on the "client" option with '{"progress":""}' value 1`] = ` "ValidationError: Invalid configuration object. Object has been initialized using a configuration object that does not match the API schema. - configuration.client.progress should be a boolean. @@ -110,14 +87,44 @@ exports[`options validate should throw an error on the "client" option with '{"t exports[`options validate should throw an error on the "client" option with '{"unknownOption":true}' value 1`] = ` "ValidationError: Invalid configuration object. Object has been initialized using a configuration object that does not match the API schema. - configuration.client has an unknown property 'unknownOption'. These properties are valid: - object { transport?, host?, path?, port?, logging?, progress?, overlay?, needClientEntry?, hotEntry? } + object { transport?, logging?, progress?, overlay?, needClientEntry?, hotEntry?, webSocketURL? } -> Specifies client properties. https://webpack.js.org/configuration/dev-server/#devserverclient" `; +exports[`options validate should throw an error on the "client" option with '{"webSocketURL":{"host":""}}' value 1`] = ` +"ValidationError: Invalid configuration object. Object has been initialized using a configuration object that does not match the API schema. + - configuration.client.webSocketURL.host should be an non-empty string. + -> Tells clients connected to devServer to use the provided host." +`; + +exports[`options validate should throw an error on the "client" option with '{"webSocketURL":{"host":true,"path":"","port":8080}}' value 1`] = ` +"ValidationError: Invalid configuration object. Object has been initialized using a configuration object that does not match the API schema. + - configuration.client.webSocketURL.host should be a non-empty string. + -> Tells clients connected to devServer to use the provided host." +`; + +exports[`options validate should throw an error on the "client" option with '{"webSocketURL":{"path":true}}' value 1`] = ` +"ValidationError: Invalid configuration object. Object has been initialized using a configuration object that does not match the API schema. + - configuration.client.webSocketURL.path should be a string. + -> Tells clients connected to devServer to use the provided path to connect." +`; + +exports[`options validate should throw an error on the "client" option with '{"webSocketURL":{"port":""}}' value 1`] = ` +"ValidationError: Invalid configuration object. Object has been initialized using a configuration object that does not match the API schema. + - configuration.client.webSocketURL.port should be a number. + -> Tells clients connected to devServer to use the provided port." +`; + +exports[`options validate should throw an error on the "client" option with '{"webSocketURL":{"port":true}}' value 1`] = ` +"ValidationError: Invalid configuration object. Object has been initialized using a configuration object that does not match the API schema. + - configuration.client.webSocketURL.port should be a number. + -> Tells clients connected to devServer to use the provided port." +`; + exports[`options validate should throw an error on the "client" option with 'whoops!' value 1`] = ` "ValidationError: Invalid configuration object. Object has been initialized using a configuration object that does not match the API schema. - configuration.client should be an object: - object { transport?, host?, path?, port?, logging?, progress?, overlay?, needClientEntry?, hotEntry? } + object { transport?, logging?, progress?, overlay?, needClientEntry?, hotEntry?, webSocketURL? } -> Specifies client properties. https://webpack.js.org/configuration/dev-server/#devserverclient" `; @@ -420,12 +427,6 @@ exports[`options validate should throw an error on the "proxy" option with 'func [object { … } | function, ...] (should not have fewer than 1 item)" `; -exports[`options validate should throw an error on the "public" option with 'false' value 1`] = ` -"ValidationError: Invalid configuration object. Object has been initialized using a configuration object that does not match the API schema. - - configuration.public should be a string. - -> When using dev server and you're proxying dev-server, the client script does not always know where to connect to. It will try to guess the URL of the server based on window.location, but if that fails you'll need to use this. https://webpack.js.org/configuration/dev-server/#devserverpublic" -`; - exports[`options validate should throw an error on the "static" option with '' value 1`] = ` "ValidationError: Invalid configuration object. Object has been initialized using a configuration object that does not match the API schema. - configuration.static should be an non-empty string." diff --git a/test/__snapshots__/validate-options.test.js.snap.webpack5 b/test/__snapshots__/validate-options.test.js.snap.webpack5 index 5580b1b45f..1aa6a376e2 100644 --- a/test/__snapshots__/validate-options.test.js.snap.webpack5 +++ b/test/__snapshots__/validate-options.test.js.snap.webpack5 @@ -12,12 +12,6 @@ exports[`options validate should throw an error on the "bonjour" option with '' -> Options for bonjour, description available at https://github.com/watson/bonjour#initializing" `; -exports[`options validate should throw an error on the "client" option with '{"host":true,"path":"","port":8080}' value 1`] = ` -"ValidationError: Invalid configuration object. Object has been initialized using a configuration object that does not match the API schema. - - configuration.client.host should be a string. - -> Tells clients connected to devServer to use the provided host." -`; - exports[`options validate should throw an error on the "client" option with '{"hotEntry":[""]}' value 1`] = ` "ValidationError: Invalid configuration object. Object has been initialized using a configuration object that does not match the API schema. - configuration.client.hotEntry should be one of these: @@ -73,23 +67,6 @@ exports[`options validate should throw an error on the "client" option with '{"o -> Show a full-screen overlay in the browser when there are compiler warnings." `; -exports[`options validate should throw an error on the "client" option with '{"path":true}' value 1`] = ` -"ValidationError: Invalid configuration object. Object has been initialized using a configuration object that does not match the API schema. - - configuration.client.path should be a string. - -> Tells clients connected to devServer to use the provided path to connect." -`; - -exports[`options validate should throw an error on the "client" option with '{"port":true}' value 1`] = ` -"ValidationError: Invalid configuration object. Object has been initialized using a configuration object that does not match the API schema. - - configuration.client.port should be one of these: - number | string | \\"auto\\" - -> Tells clients connected to devServer to use the provided port. - Details: - * configuration.client.port should be a number. - * configuration.client.port should be a string. - * configuration.client.port should be \\"auto\\"." -`; - exports[`options validate should throw an error on the "client" option with '{"progress":""}' value 1`] = ` "ValidationError: Invalid configuration object. Object has been initialized using a configuration object that does not match the API schema. - configuration.client.progress should be a boolean. @@ -110,14 +87,44 @@ exports[`options validate should throw an error on the "client" option with '{"t exports[`options validate should throw an error on the "client" option with '{"unknownOption":true}' value 1`] = ` "ValidationError: Invalid configuration object. Object has been initialized using a configuration object that does not match the API schema. - configuration.client has an unknown property 'unknownOption'. These properties are valid: - object { transport?, host?, path?, port?, logging?, progress?, overlay?, needClientEntry?, hotEntry? } + object { transport?, logging?, progress?, overlay?, needClientEntry?, hotEntry?, webSocketURL? } -> Specifies client properties. https://webpack.js.org/configuration/dev-server/#devserverclient" `; +exports[`options validate should throw an error on the "client" option with '{"webSocketURL":{"host":""}}' value 1`] = ` +"ValidationError: Invalid configuration object. Object has been initialized using a configuration object that does not match the API schema. + - configuration.client.webSocketURL.host should be an non-empty string. + -> Tells clients connected to devServer to use the provided host." +`; + +exports[`options validate should throw an error on the "client" option with '{"webSocketURL":{"host":true,"path":"","port":8080}}' value 1`] = ` +"ValidationError: Invalid configuration object. Object has been initialized using a configuration object that does not match the API schema. + - configuration.client.webSocketURL.host should be a non-empty string. + -> Tells clients connected to devServer to use the provided host." +`; + +exports[`options validate should throw an error on the "client" option with '{"webSocketURL":{"path":true}}' value 1`] = ` +"ValidationError: Invalid configuration object. Object has been initialized using a configuration object that does not match the API schema. + - configuration.client.webSocketURL.path should be a string. + -> Tells clients connected to devServer to use the provided path to connect." +`; + +exports[`options validate should throw an error on the "client" option with '{"webSocketURL":{"port":""}}' value 1`] = ` +"ValidationError: Invalid configuration object. Object has been initialized using a configuration object that does not match the API schema. + - configuration.client.webSocketURL.port should be a number. + -> Tells clients connected to devServer to use the provided port." +`; + +exports[`options validate should throw an error on the "client" option with '{"webSocketURL":{"port":true}}' value 1`] = ` +"ValidationError: Invalid configuration object. Object has been initialized using a configuration object that does not match the API schema. + - configuration.client.webSocketURL.port should be a number. + -> Tells clients connected to devServer to use the provided port." +`; + exports[`options validate should throw an error on the "client" option with 'whoops!' value 1`] = ` "ValidationError: Invalid configuration object. Object has been initialized using a configuration object that does not match the API schema. - configuration.client should be an object: - object { transport?, host?, path?, port?, logging?, progress?, overlay?, needClientEntry?, hotEntry? } + object { transport?, logging?, progress?, overlay?, needClientEntry?, hotEntry?, webSocketURL? } -> Specifies client properties. https://webpack.js.org/configuration/dev-server/#devserverclient" `; @@ -420,12 +427,6 @@ exports[`options validate should throw an error on the "proxy" option with 'func [object { … } | function, ...] (should not have fewer than 1 item)" `; -exports[`options validate should throw an error on the "public" option with 'false' value 1`] = ` -"ValidationError: Invalid configuration object. Object has been initialized using a configuration object that does not match the API schema. - - configuration.public should be a string. - -> When using dev server and you're proxying dev-server, the client script does not always know where to connect to. It will try to guess the URL of the server based on window.location, but if that fails you'll need to use this. https://webpack.js.org/configuration/dev-server/#devserverpublic" -`; - exports[`options validate should throw an error on the "static" option with '' value 1`] = ` "ValidationError: Invalid configuration object. Object has been initialized using a configuration object that does not match the API schema. - configuration.static should be an non-empty string." diff --git a/test/cli/__snapshots__/cli.test.js.snap.webpack4 b/test/cli/__snapshots__/cli.test.js.snap.webpack4 index 917825ddfd..01d2abf391 100644 --- a/test/cli/__snapshots__/cli.test.js.snap.webpack4 +++ b/test/cli/__snapshots__/cli.test.js.snap.webpack4 @@ -271,8 +271,6 @@ Options: Page Applications. --compress Enable gzip compression. --no-compress Disable gzip compression. - --public The public hostname/ip address of the - server. --firewall [value...] Enable firewall or set hosts that are allowed to access the dev server. --no-firewall Disable firewall. diff --git a/test/cli/__snapshots__/cli.test.js.snap.webpack5 b/test/cli/__snapshots__/cli.test.js.snap.webpack5 index ffad849682..4773f47bdb 100644 --- a/test/cli/__snapshots__/cli.test.js.snap.webpack5 +++ b/test/cli/__snapshots__/cli.test.js.snap.webpack5 @@ -272,8 +272,6 @@ Options: Page Applications. --compress Enable gzip compression. --no-compress Disable gzip compression. - --public The public hostname/ip address of the - server. --firewall [value...] Enable firewall or set hosts that are allowed to access the dev server. --no-firewall Disable firewall. diff --git a/test/cli/cli.test.js b/test/cli/cli.test.js index bc25838300..af3484bdf3 100644 --- a/test/cli/cli.test.js +++ b/test/cli/cli.test.js @@ -723,7 +723,10 @@ describe('CLI', () => { it('should exit the process when SIGINT is detected', (done) => { const cliPath = path.resolve(__dirname, '../../bin/webpack-dev-server.js'); - const examplePath = path.resolve(__dirname, '../../examples/cli/public'); + const examplePath = path.resolve( + __dirname, + '../../examples/cli/web-socket-url' + ); const cp = execa('node', [cliPath], { cwd: examplePath }); cp.stdout.on('data', (data) => { @@ -765,7 +768,10 @@ describe('CLI', () => { it('should exit the process when stdin ends if --watch-options-stdin', (done) => { const cliPath = path.resolve(__dirname, '../../bin/webpack-dev-server.js'); - const examplePath = path.resolve(__dirname, '../../examples/cli/public'); + const examplePath = path.resolve( + __dirname, + '../../examples/cli/web-socket-url' + ); const cp = execa('node', [cliPath, '--watch-options-stdin'], { cwd: examplePath, }); diff --git a/test/client/utils/__snapshots__/parseURL.test.js.snap.webpack4 b/test/client/utils/__snapshots__/parseURL.test.js.snap.webpack4 index 04816ac822..fff30d1ae3 100644 --- a/test/client/utils/__snapshots__/parseURL.test.js.snap.webpack4 +++ b/test/client/utils/__snapshots__/parseURL.test.js.snap.webpack4 @@ -190,6 +190,7 @@ Url { exports[`'parseURL' function should return the url when __resourceQuery is 'undefined' 1`] = ` Url { "auth": null, + "fromCurrentScript": true, "hash": null, "host": "localhost", "hostname": "localhost", @@ -229,6 +230,7 @@ exports[`'parseURL' function should return the url when the current script sourc exports[`'parseURL' function should return the url when the current script source is 'undefined' 1`] = ` Url { "auth": null, + "fromCurrentScript": true, "hash": null, "host": "localhost", "hostname": "localhost", diff --git a/test/client/utils/__snapshots__/parseURL.test.js.snap.webpack5 b/test/client/utils/__snapshots__/parseURL.test.js.snap.webpack5 index 04816ac822..fff30d1ae3 100644 --- a/test/client/utils/__snapshots__/parseURL.test.js.snap.webpack5 +++ b/test/client/utils/__snapshots__/parseURL.test.js.snap.webpack5 @@ -190,6 +190,7 @@ Url { exports[`'parseURL' function should return the url when __resourceQuery is 'undefined' 1`] = ` Url { "auth": null, + "fromCurrentScript": true, "hash": null, "host": "localhost", "hostname": "localhost", @@ -229,6 +230,7 @@ exports[`'parseURL' function should return the url when the current script sourc exports[`'parseURL' function should return the url when the current script source is 'undefined' 1`] = ` Url { "auth": null, + "fromCurrentScript": true, "hash": null, "host": "localhost", "hostname": "localhost", diff --git a/test/client/utils/createSocketURL.test.js b/test/client/utils/createSocketURL.test.js index 81ac0c3d6e..2da4114039 100644 --- a/test/client/utils/createSocketURL.test.js +++ b/test/client/utils/createSocketURL.test.js @@ -3,30 +3,35 @@ describe("'createSocketURL' function ", () => { const samples = [ // __resourceQuery, location and socket URL - ['?http://example.com', 'http://example.com', 'ws://example.com/ws'], - ['?http://example.com', 'http://something.com', 'ws://example.com/ws'], - [null, 'http://example.com', 'ws://example.com/ws'], - ['?https://example.com', 'https://example.com', 'wss://example.com/ws'], - [null, 'https://example.com', 'wss://example.com/ws'], + ['?http://example.com/ws', 'http://example.com', 'ws://example.com/ws'], [ - '?http://example.com&port=8080', - 'http://example.com:8080', - 'ws://example.com:8080/ws', + `?${encodeURIComponent('http://example.com/ws')}`, + 'http://example.com', + 'ws://example.com/ws', + ], + [ + `?${encodeURIComponent('http://example.com/ws?foo=bar')}`, + 'http://example.com', + 'ws://example.com/ws', ], + ['?http://example.com/ws', 'http://something.com', 'ws://example.com/ws'], + [null, 'http://example.com', 'ws://example.com/ws'], + ['?https://example.com/ws', 'https://example.com', 'wss://example.com/ws'], + [null, 'https://example.com', 'wss://example.com/ws'], [ - '?http://example.com:0', + '?http://example.com:0/ws', 'http://example.com:8080', 'ws://example.com:8080/ws', ], [null, 'http://example.com:8080', 'ws://example.com:8080/ws'], [ - '?http://example.com/path/foo.js', + '?http://example.com/custom-path/', 'http://example.com/foo/bar', - 'ws://example.com/ws', + 'ws://example.com/custom-path/', ], [null, 'http://example.com/foo/bar', 'ws://example.com/ws'], [ - '?http://user:password@localhost/', + '?http://user:password@localhost/ws', 'http://user:password@localhost/', 'ws://user:password@localhost/ws', ], @@ -36,7 +41,7 @@ describe("'createSocketURL' function ", () => { 'ws://user:password@localhost/ws', ], [ - '?http://user:password@localhost:8080/', + '?http://user:password@localhost:8080/ws', 'http://user:password@localhost/', 'ws://user:password@localhost:8080/ws', ], @@ -46,71 +51,44 @@ describe("'createSocketURL' function ", () => { 'http://user:password@localhost:8080/', 'ws://user:password@localhost:8080/ws', ], - ['?http://0.0.0.0', 'http://127.0.0.1', 'ws://127.0.0.1/ws'], - ['?http://0.0.0.0', 'http://192.168.0.1', 'ws://192.168.0.1/ws'], - ['?http://0.0.0.0', 'https://192.168.0.1', 'wss://192.168.0.1/ws'], - ['?http://0.0.0.0', 'https://example.com', 'wss://example.com/ws'], + ['?http://0.0.0.0/ws', 'http://127.0.0.1', 'ws://127.0.0.1/ws'], + ['?http://0.0.0.0/ws', 'http://192.168.0.1', 'ws://192.168.0.1/ws'], + ['?http://0.0.0.0/ws', 'https://192.168.0.1', 'wss://192.168.0.1/ws'], + ['?http://0.0.0.0/ws', 'https://example.com', 'wss://example.com/ws'], [ - '?http://0.0.0.0', + '?http://0.0.0.0/ws', 'https://example.com:8080', 'wss://example.com:8080/ws', ], [ - '?https://0.0.0.0', + '?https://0.0.0.0/ws', 'https://example.com:8080', 'wss://example.com:8080/ws', ], + ['?http://localhost/ws', 'http://localhost', 'ws://localhost/ws'], [ - '?http://0.0.0.0&port=9090', - 'https://example.com', - 'wss://example.com:9090/ws', - ], - [ - '?http://0.0.0.0&port=9090', - 'https://example.com:8080', - 'wss://example.com:9090/ws', - ], - ['?http://localhost', 'http://localhost', 'ws://localhost/ws'], - [ - '?http://localhost:8080', + '?http://localhost:8080/ws', 'http://localhost:8080', 'ws://localhost:8080/ws', ], [ - '?https://localhost:8080', + '?https://localhost:8080/ws', 'https://localhost:8080', 'wss://localhost:8080/ws', ], [null, 'https://localhost:8080', 'wss://localhost:8080/ws'], - ['?http://127.0.0.1', 'http://something.com', 'ws://127.0.0.1/ws'], - - ['?http://127.0.0.1', 'https://something.com', 'ws://127.0.0.1/ws'], - - ['?https://127.0.0.1', 'http://something.com', 'wss://127.0.0.1/ws'], + ['?http://127.0.0.1/ws', 'http://something.com', 'ws://127.0.0.1/ws'], + ['?http://127.0.0.1/ws', 'https://something.com', 'ws://127.0.0.1/ws'], + ['?https://127.0.0.1/ws', 'http://something.com', 'wss://127.0.0.1/ws'], [null, 'http://127.0.0.1', 'ws://127.0.0.1/ws'], [null, 'http://127.0.0.1:8080', 'ws://127.0.0.1:8080/ws'], [null, 'https://127.0.0.1', 'wss://127.0.0.1/ws'], - [ - '?https://example.com&host=example.com', - 'http://something.com', - 'wss://example.com/ws', - ], - [ - '?https://example.com&path=custom', - 'http://something.com', - 'wss://example.com/custom', - ], - [ - '?https://example.com&path=/custom', - 'http://something.com', - 'wss://example.com/custom', - ], - ['?http://[::]', 'http://something.com', 'ws://something.com/ws'], - ['?http://[::]', 'https://something.com', 'wss://something.com/ws'], - ['?http://[::1]:8080/', 'http://[::1]:8080/', 'ws://[::1]:8080/ws'], - ['?https://[::1]:8080/', 'http://[::1]:8080/', 'wss://[::1]:8080/ws'], - [null, 'http://[::1]:8080/', 'ws://[::1]:8080/ws'], - [null, 'https://[::1]:8080/', 'wss://[::1]:8080/ws'], + ['?http://[::]/ws', 'http://something.com', 'ws://something.com/ws'], + ['?http://[::]/ws', 'https://something.com', 'wss://something.com/ws'], + ['?http://[::1]:8080/ws', 'http://[::1]:8080/', 'ws://[::1]:8080/ws'], + ['?https://[::1]:8080/ws', 'http://[::1]:8080/', 'wss://[::1]:8080/ws'], + [null, 'http://[::1]:8080/ws', 'ws://[::1]:8080/ws'], + [null, 'https://[::1]:8080/ws', 'wss://[::1]:8080/ws'], [null, 'file:///home/user/project/index.html', 'ws://localhost/ws'], [null, 'chrome-extension://localhost/', 'ws://localhost/ws'], [null, 'file://localhost/', 'ws://localhost/ws'], diff --git a/test/e2e/DevServer.test.js b/test/e2e/DevServer.test.js index 87e14c269d..dd09b3ff7a 100644 --- a/test/e2e/DevServer.test.js +++ b/test/e2e/DevServer.test.js @@ -96,7 +96,7 @@ describe('DevServer', () => { testBin(null, './test/fixtures/dev-server/client-default-path-config.js') .then((output) => { expect(output.exitCode).toEqual(0); - expect(output.stdout).toContain('&path=/ws'); + expect(output.stdout).toContain('ws%3A%2F%2F0.0.0.0%2Fws'); done(); }) .catch(done); @@ -106,7 +106,7 @@ describe('DevServer', () => { testBin(null, './test/fixtures/dev-server/client-custom-path-config.js') .then((output) => { expect(output.exitCode).toEqual(0); - expect(output.stdout).toContain('&path=/custom/path'); + expect(output.stdout).toContain('ws%3A%2F%2F0.0.0.0%2Fcustom%2Fpath'); done(); }) .catch(done); diff --git a/test/e2e/__snapshots__/ClientOptions.test.js.snap.webpack4 b/test/e2e/__snapshots__/logging.test.js.snap.webpack4 similarity index 64% rename from test/e2e/__snapshots__/ClientOptions.test.js.snap.webpack4 rename to test/e2e/__snapshots__/logging.test.js.snap.webpack4 index 92abcfef92..4ce374ca58 100644 --- a/test/e2e/__snapshots__/ClientOptions.test.js.snap.webpack4 +++ b/test/e2e/__snapshots__/logging.test.js.snap.webpack4 @@ -1,45 +1,45 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Client console.log client logging is none (default) 1`] = ` +exports[`logging client logging is none (default) 1`] = ` Array [ "Hey.", ] `; -exports[`Client console.log client logging is none (sockjs) 1`] = ` +exports[`logging client logging is none (sockjs) 1`] = ` Array [ "Hey.", ] `; -exports[`Client console.log client logging is none (ws) 1`] = ` +exports[`logging client logging is none (ws) 1`] = ` Array [ "Hey.", ] `; -exports[`Client console.log hot disabled (default) 1`] = ` +exports[`logging hot disabled (default) 1`] = ` Array [ "Hey.", "[webpack-dev-server] Live Reloading enabled.", ] `; -exports[`Client console.log hot disabled (sockjs) 1`] = ` +exports[`logging hot disabled (sockjs) 1`] = ` Array [ "Hey.", "[webpack-dev-server] Live Reloading enabled.", ] `; -exports[`Client console.log hot disabled (ws) 1`] = ` +exports[`logging hot disabled (ws) 1`] = ` Array [ "Hey.", "[webpack-dev-server] Live Reloading enabled.", ] `; -exports[`Client console.log hot enabled (default) 1`] = ` +exports[`logging hot enabled (default) 1`] = ` Array [ "Hey.", "[HMR] Waiting for update signal from WDS...", @@ -48,7 +48,7 @@ Array [ ] `; -exports[`Client console.log hot enabled (sockjs) 1`] = ` +exports[`logging hot enabled (sockjs) 1`] = ` Array [ "Hey.", "[HMR] Waiting for update signal from WDS...", @@ -57,7 +57,7 @@ Array [ ] `; -exports[`Client console.log hot enabled (ws) 1`] = ` +exports[`logging hot enabled (ws) 1`] = ` Array [ "Hey.", "[HMR] Waiting for update signal from WDS...", @@ -66,18 +66,18 @@ Array [ ] `; -exports[`Client console.log liveReload & hot are disabled (default) 1`] = ` +exports[`logging liveReload & hot are disabled (default) 1`] = ` Array [ "Hey.", - "WebSocket connection to 'ws://localhost:8096/ws' failed: Error during WebSocket handshake: Unexpected response code: 404", - "WebSocket connection to 'ws://localhost:8096/ws' failed: Error during WebSocket handshake: Unexpected response code: 404", + "WebSocket connection to 'ws://localhost:8098/ws' failed: Error during WebSocket handshake: Unexpected response code: 404", + "WebSocket connection to 'ws://localhost:8098/ws' failed: Error during WebSocket handshake: Unexpected response code: 404", "[webpack-dev-server] Disconnected!", "[webpack-dev-server] JSHandle@object", "[webpack-dev-server] JSHandle@object", ] `; -exports[`Client console.log liveReload & hot are disabled (sockjs) 1`] = ` +exports[`logging liveReload & hot are disabled (sockjs) 1`] = ` Array [ "Failed to load resource: the server responded with a status of 404 (Not Found)", "Failed to load resource: the server responded with a status of 404 (Not Found)", @@ -86,18 +86,18 @@ Array [ ] `; -exports[`Client console.log liveReload & hot are disabled (ws) 1`] = ` +exports[`logging liveReload & hot are disabled (ws) 1`] = ` Array [ "Hey.", - "WebSocket connection to 'ws://localhost:8096/ws' failed: Error during WebSocket handshake: Unexpected response code: 404", - "WebSocket connection to 'ws://localhost:8096/ws' failed: Error during WebSocket handshake: Unexpected response code: 404", + "WebSocket connection to 'ws://localhost:8098/ws' failed: Error during WebSocket handshake: Unexpected response code: 404", + "WebSocket connection to 'ws://localhost:8098/ws' failed: Error during WebSocket handshake: Unexpected response code: 404", "[webpack-dev-server] Disconnected!", "[webpack-dev-server] JSHandle@object", "[webpack-dev-server] JSHandle@object", ] `; -exports[`Client console.log liveReload disabled (default) 1`] = ` +exports[`logging liveReload disabled (default) 1`] = ` Array [ "Hey.", "[HMR] Waiting for update signal from WDS...", @@ -105,7 +105,7 @@ Array [ ] `; -exports[`Client console.log liveReload disabled (sockjs) 1`] = ` +exports[`logging liveReload disabled (sockjs) 1`] = ` Array [ "Hey.", "[HMR] Waiting for update signal from WDS...", @@ -113,7 +113,7 @@ Array [ ] `; -exports[`Client console.log liveReload disabled (ws) 1`] = ` +exports[`logging liveReload disabled (ws) 1`] = ` Array [ "Hey.", "[HMR] Waiting for update signal from WDS...", @@ -121,7 +121,7 @@ Array [ ] `; -exports[`Client console.log liveReload enabled (default) 1`] = ` +exports[`logging liveReload enabled (default) 1`] = ` Array [ "Hey.", "[HMR] Waiting for update signal from WDS...", @@ -130,7 +130,7 @@ Array [ ] `; -exports[`Client console.log liveReload enabled (sockjs) 1`] = ` +exports[`logging liveReload enabled (sockjs) 1`] = ` Array [ "Hey.", "[HMR] Waiting for update signal from WDS...", @@ -139,7 +139,7 @@ Array [ ] `; -exports[`Client console.log liveReload enabled (ws) 1`] = ` +exports[`logging liveReload enabled (ws) 1`] = ` Array [ "Hey.", "[HMR] Waiting for update signal from WDS...", diff --git a/test/e2e/__snapshots__/ClientOptions.test.js.snap.webpack5 b/test/e2e/__snapshots__/logging.test.js.snap.webpack5 similarity index 64% rename from test/e2e/__snapshots__/ClientOptions.test.js.snap.webpack5 rename to test/e2e/__snapshots__/logging.test.js.snap.webpack5 index 92abcfef92..4ce374ca58 100644 --- a/test/e2e/__snapshots__/ClientOptions.test.js.snap.webpack5 +++ b/test/e2e/__snapshots__/logging.test.js.snap.webpack5 @@ -1,45 +1,45 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Client console.log client logging is none (default) 1`] = ` +exports[`logging client logging is none (default) 1`] = ` Array [ "Hey.", ] `; -exports[`Client console.log client logging is none (sockjs) 1`] = ` +exports[`logging client logging is none (sockjs) 1`] = ` Array [ "Hey.", ] `; -exports[`Client console.log client logging is none (ws) 1`] = ` +exports[`logging client logging is none (ws) 1`] = ` Array [ "Hey.", ] `; -exports[`Client console.log hot disabled (default) 1`] = ` +exports[`logging hot disabled (default) 1`] = ` Array [ "Hey.", "[webpack-dev-server] Live Reloading enabled.", ] `; -exports[`Client console.log hot disabled (sockjs) 1`] = ` +exports[`logging hot disabled (sockjs) 1`] = ` Array [ "Hey.", "[webpack-dev-server] Live Reloading enabled.", ] `; -exports[`Client console.log hot disabled (ws) 1`] = ` +exports[`logging hot disabled (ws) 1`] = ` Array [ "Hey.", "[webpack-dev-server] Live Reloading enabled.", ] `; -exports[`Client console.log hot enabled (default) 1`] = ` +exports[`logging hot enabled (default) 1`] = ` Array [ "Hey.", "[HMR] Waiting for update signal from WDS...", @@ -48,7 +48,7 @@ Array [ ] `; -exports[`Client console.log hot enabled (sockjs) 1`] = ` +exports[`logging hot enabled (sockjs) 1`] = ` Array [ "Hey.", "[HMR] Waiting for update signal from WDS...", @@ -57,7 +57,7 @@ Array [ ] `; -exports[`Client console.log hot enabled (ws) 1`] = ` +exports[`logging hot enabled (ws) 1`] = ` Array [ "Hey.", "[HMR] Waiting for update signal from WDS...", @@ -66,18 +66,18 @@ Array [ ] `; -exports[`Client console.log liveReload & hot are disabled (default) 1`] = ` +exports[`logging liveReload & hot are disabled (default) 1`] = ` Array [ "Hey.", - "WebSocket connection to 'ws://localhost:8096/ws' failed: Error during WebSocket handshake: Unexpected response code: 404", - "WebSocket connection to 'ws://localhost:8096/ws' failed: Error during WebSocket handshake: Unexpected response code: 404", + "WebSocket connection to 'ws://localhost:8098/ws' failed: Error during WebSocket handshake: Unexpected response code: 404", + "WebSocket connection to 'ws://localhost:8098/ws' failed: Error during WebSocket handshake: Unexpected response code: 404", "[webpack-dev-server] Disconnected!", "[webpack-dev-server] JSHandle@object", "[webpack-dev-server] JSHandle@object", ] `; -exports[`Client console.log liveReload & hot are disabled (sockjs) 1`] = ` +exports[`logging liveReload & hot are disabled (sockjs) 1`] = ` Array [ "Failed to load resource: the server responded with a status of 404 (Not Found)", "Failed to load resource: the server responded with a status of 404 (Not Found)", @@ -86,18 +86,18 @@ Array [ ] `; -exports[`Client console.log liveReload & hot are disabled (ws) 1`] = ` +exports[`logging liveReload & hot are disabled (ws) 1`] = ` Array [ "Hey.", - "WebSocket connection to 'ws://localhost:8096/ws' failed: Error during WebSocket handshake: Unexpected response code: 404", - "WebSocket connection to 'ws://localhost:8096/ws' failed: Error during WebSocket handshake: Unexpected response code: 404", + "WebSocket connection to 'ws://localhost:8098/ws' failed: Error during WebSocket handshake: Unexpected response code: 404", + "WebSocket connection to 'ws://localhost:8098/ws' failed: Error during WebSocket handshake: Unexpected response code: 404", "[webpack-dev-server] Disconnected!", "[webpack-dev-server] JSHandle@object", "[webpack-dev-server] JSHandle@object", ] `; -exports[`Client console.log liveReload disabled (default) 1`] = ` +exports[`logging liveReload disabled (default) 1`] = ` Array [ "Hey.", "[HMR] Waiting for update signal from WDS...", @@ -105,7 +105,7 @@ Array [ ] `; -exports[`Client console.log liveReload disabled (sockjs) 1`] = ` +exports[`logging liveReload disabled (sockjs) 1`] = ` Array [ "Hey.", "[HMR] Waiting for update signal from WDS...", @@ -113,7 +113,7 @@ Array [ ] `; -exports[`Client console.log liveReload disabled (ws) 1`] = ` +exports[`logging liveReload disabled (ws) 1`] = ` Array [ "Hey.", "[HMR] Waiting for update signal from WDS...", @@ -121,7 +121,7 @@ Array [ ] `; -exports[`Client console.log liveReload enabled (default) 1`] = ` +exports[`logging liveReload enabled (default) 1`] = ` Array [ "Hey.", "[HMR] Waiting for update signal from WDS...", @@ -130,7 +130,7 @@ Array [ ] `; -exports[`Client console.log liveReload enabled (sockjs) 1`] = ` +exports[`logging liveReload enabled (sockjs) 1`] = ` Array [ "Hey.", "[HMR] Waiting for update signal from WDS...", @@ -139,7 +139,7 @@ Array [ ] `; -exports[`Client console.log liveReload enabled (ws) 1`] = ` +exports[`logging liveReload enabled (ws) 1`] = ` Array [ "Hey.", "[HMR] Waiting for update signal from WDS...", diff --git a/test/e2e/Client.test.js b/test/e2e/hot-and-live-reload.test.js similarity index 95% rename from test/e2e/Client.test.js rename to test/e2e/hot-and-live-reload.test.js index 798a43f300..c2a21fbd76 100644 --- a/test/e2e/Client.test.js +++ b/test/e2e/hot-and-live-reload.test.js @@ -27,12 +27,19 @@ describe('reload', () => { shouldRefresh: false, }, { - title: 'hot with transportMode.client sockjs', + title: 'hot with sockjs websocket server', options: { webSocketServer: 'sockjs', }, shouldRefresh: false, }, + { + title: 'hot with ws websocket server', + options: { + webSocketServer: 'ws', + }, + shouldRefresh: false, + }, { title: 'reload without hot', options: { @@ -52,9 +59,9 @@ describe('reload', () => { const options = Object.assign( {}, { - static: false, - port, host: '0.0.0.0', + port, + static: false, }, mode.options ); @@ -95,6 +102,7 @@ describe('reload', () => { ) { refreshed = true; } + req.continue(); }); page.waitForTimeout(reloadReadyDelay).then(() => { diff --git a/test/e2e/logging.test.js b/test/e2e/logging.test.js new file mode 100644 index 0000000000..a3f877f7c9 --- /dev/null +++ b/test/e2e/logging.test.js @@ -0,0 +1,94 @@ +'use strict'; + +const testServer = require('../helpers/test-server'); +const config = require('../fixtures/client-config/webpack.config'); +const runBrowser = require('../helpers/run-browser'); +const port = require('../ports-map').logging; +const { beforeBrowserCloseDelay } = require('../helpers/puppeteer-constants'); + +describe('logging', () => { + const baseOptions = { + host: '0.0.0.0', + port, + }; + const webSocketServerTypesLog = [ + {}, + { webSocketServer: 'sockjs' }, + { webSocketServer: 'ws' }, + ]; + + const cases = [ + { + title: 'hot disabled', + options: { + hot: false, + }, + }, + { + title: 'hot enabled', + options: { + hot: true, + }, + }, + { + title: 'liveReload disabled', + options: { + liveReload: false, + }, + }, + { + title: 'liveReload enabled', + options: { + liveReload: true, + }, + }, + { + title: 'liveReload & hot are disabled', + options: { + liveReload: false, + hot: false, + }, + }, + { + title: 'client logging is none', + options: { + client: { + logging: 'none', + }, + }, + }, + ]; + + webSocketServerTypesLog.forEach(async (mode) => { + cases.forEach(async ({ title, options }) => { + title += ` (${ + Object.keys(mode).length ? mode.webSocketServer : 'default' + })`; + + options = { ...mode, ...options }; + + const testOptions = Object.assign({}, baseOptions, options); + + it(title, (done) => { + testServer.startAwaitingCompilation(config, testOptions, async () => { + const res = []; + const { page, browser } = await runBrowser(); + + page.goto(`http://localhost:${port}/main`); + page.on('console', ({ _text }) => { + res.push(_text); + }); + + // wait for load before closing the browser + await page.waitForNavigation({ waitUntil: 'load' }); + await page.waitForTimeout(beforeBrowserCloseDelay); + await browser.close(); + + // Order doesn't matter, maybe we should improve that in future + await expect(res.sort()).toMatchSnapshot(); + await testServer.close(done); + }); + }); + }); + }); +}); diff --git a/test/e2e/ClientOptions.test.js b/test/e2e/web-socket-server-and-url.test.js similarity index 79% rename from test/e2e/ClientOptions.test.js rename to test/e2e/web-socket-server-and-url.test.js index b0fff4eb0e..79b9eac55e 100644 --- a/test/e2e/ClientOptions.test.js +++ b/test/e2e/web-socket-server-and-url.test.js @@ -93,7 +93,7 @@ for (const webSocketServerType of webSocketServerTypes) { runBrowser().then(async ({ page, browser }) => { waitForTest(browser, page, /ws/, (websocketUrl) => { expect(websocketUrl).toContain( - `${websocketUrlProtocol}://${proxyHost}:${devServerPort}/ws` + `${websocketUrlProtocol}://${devServerHost}:${devServerPort}/ws` ); done(); @@ -160,7 +160,7 @@ for (const webSocketServerType of webSocketServerTypes) { runBrowser().then(async ({ page, browser }) => { waitForTest(browser, page, /ws/, (websocketUrl) => { expect(websocketUrl).toContain( - `${websocketUrlProtocol}://${proxyHost}:${proxyPort}/ws` + `${websocketUrlProtocol}://${devServerHost}:${devServerPort}/ws` ); done(); @@ -196,10 +196,14 @@ for (const webSocketServerType of webSocketServerTypes) { beforeAll((done) => { const options = { - client: { host: devServerHost }, - webSocketServer: webSocketServerType, + client: { + webSocketURL: { + host: devServerHost, + }, + }, port: devServerPort, host: devServerHost, + webSocketServer: webSocketServerType, firewall: false, hot: true, static: true, @@ -248,8 +252,10 @@ for (const webSocketServerType of webSocketServerTypes) { port: port2, host: '0.0.0.0', client: { - path: '/foo/test/bar/', - port: port3, + webSocketURL: { + path: '/foo/test/bar/', + port: port3, + }, }, }; @@ -275,14 +281,16 @@ for (const webSocketServerType of webSocketServerTypes) { }); }); - describe('should work with custom client port and without path', () => { + describe('should work with custom client port', () => { beforeAll((done) => { const options = { webSocketServer: webSocketServerType, port: port2, host: '0.0.0.0', client: { - port: port3, + webSocketURL: { + port: port3, + }, }, }; @@ -308,14 +316,16 @@ for (const webSocketServerType of webSocketServerTypes) { }); }); - describe('should work with custom client', () => { + describe('should work with custom client host', () => { beforeAll((done) => { const options = { webSocketServer: webSocketServerType, port: port2, host: '0.0.0.0', client: { - host: 'myhost.test', + webSocketURL: { + host: 'myhost.test', + }, }, }; testServer.startAwaitingCompilation(config, options, done); @@ -347,9 +357,11 @@ for (const webSocketServerType of webSocketServerTypes) { port: port2, host: '0.0.0.0', client: { - host: 'myhost', - port: port3, - path: '/foo/test/bar/', + webSocketURL: { + host: 'myhost', + port: port3, + path: '/foo/test/bar/', + }, }, }; @@ -375,15 +387,14 @@ for (const webSocketServerType of webSocketServerTypes) { }); }); - describe('should work with the "public" option and custom client path', () => { + describe('should work with the "client.webSocketURL" option and custom client path', () => { beforeAll((done) => { const options = { webSocketServer: webSocketServerType, port: port2, host: '0.0.0.0', - public: 'myhost.test', client: { - path: '/foo/test/bar/', + webSocketURL: `ws://myhost.test:${port2}/foo/test/bar/`, }, }; @@ -409,90 +420,3 @@ for (const webSocketServerType of webSocketServerTypes) { }); }); } - -describe('Client console.log', () => { - const baseOptions = { - port: port2, - host: '0.0.0.0', - }; - const webSocketServerTypesLog = [ - {}, - { webSocketServer: 'sockjs' }, - { webSocketServer: 'ws' }, - ]; - - const cases = [ - { - title: 'hot disabled', - options: { - hot: false, - }, - }, - { - title: 'hot enabled', - options: { - hot: true, - }, - }, - { - title: 'liveReload disabled', - options: { - liveReload: false, - }, - }, - { - title: 'liveReload enabled', - options: { - liveReload: true, - }, - }, - { - title: 'liveReload & hot are disabled', - options: { - liveReload: false, - hot: false, - }, - }, - { - title: 'client logging is none', - options: { - client: { - logging: 'none', - }, - }, - }, - ]; - - webSocketServerTypesLog.forEach(async (mode) => { - cases.forEach(async ({ title, options }) => { - title += ` (${ - Object.keys(mode).length ? mode.webSocketServer : 'default' - })`; - - options = { ...mode, ...options }; - - const testOptions = Object.assign({}, baseOptions, options); - - it(title, (done) => { - testServer.startAwaitingCompilation(config, testOptions, async () => { - const res = []; - const { page, browser } = await runBrowser(); - - page.goto(`http://localhost:${port2}/main`); - page.on('console', ({ _text }) => { - res.push(_text); - }); - - // wait for load before closing the browser - await page.waitForNavigation({ waitUntil: 'load' }); - await page.waitForTimeout(beforeBrowserCloseDelay); - await browser.close(); - - // Order doesn't matter, maybe we should improve that in future - await expect(res.sort()).toMatchSnapshot(); - await testServer.close(done); - }); - }); - }); - }); -}); diff --git a/test/ports-map.js b/test/ports-map.js index 6094b0d8f5..29b8fa2bd1 100644 --- a/test/ports-map.js +++ b/test/ports-map.js @@ -8,11 +8,11 @@ const portsList = { SockJSServer: 1, Client: 1, ClientOptions: 3, + logging: 1, MultiCompiler: 1, UniversalCompiler: 1, Server: 1, routes: 1, - createDomain: 2, 'onAfterSetupMiddleware-option': 1, 'onBeforeSetupMiddleware-option': 1, 'compress-option': 1, diff --git a/test/server/Server.test.js b/test/server/Server.test.js index d192bca202..186961043e 100644 --- a/test/server/Server.test.js +++ b/test/server/Server.test.js @@ -12,6 +12,7 @@ const port = require('../ports-map').Server; const isWebpack5 = require('../helpers/isWebpack5'); const getFreePort = Server.getFreePort; + jest.mock('sockjs/lib/transport'); const baseDevConfig = { @@ -302,7 +303,9 @@ describe('Server', () => { it('should always allow any host if options.firewall is disabled', () => { const options = { - public: 'test.host:80', + client: { + webSocketURL: 'ws://test.host:80', + }, firewall: false, }; @@ -317,9 +320,11 @@ describe('Server', () => { } }); - it('should allow any valid options.public when host is localhost', () => { + it('should allow any valid options.client.webSocketURL when host is localhost', () => { const options = { - public: 'test.host:80', + client: { + webSocketURL: 'ws://test.host:80', + }, }; const headers = { host: 'localhost', @@ -330,9 +335,11 @@ describe('Server', () => { } }); - it('should allow any valid options.public when host is 127.0.0.1', () => { + it('should allow any valid options.client.webSocketURL when host is 127.0.0.1', () => { const options = { - public: 'test.host:80', + client: { + webSocketURL: 'ws://test.host:80', + }, }; const headers = { @@ -369,9 +376,11 @@ describe('Server', () => { }); }); - it("should not allow hostnames that don't match options.public", () => { + it("should not allow hostnames that don't match options.client.webSocketURL", () => { const options = { - public: 'test.host:80', + client: { + webSocketURL: 'ws://test.host:80', + }, }; const headers = { @@ -385,14 +394,37 @@ describe('Server', () => { } }); - it('should allow urls with scheme for checking origin', () => { + it('should allow urls with scheme for checking origin when the "option.client.webSocketURL" is string', () => { + const options = { + client: { + webSocketURL: 'ws://test.host:80', + }, + }; + const headers = { + origin: 'https://test.host', + }; + + server = createServer(compiler, options); + + if (!server.checkOrigin(headers)) { + throw new Error("Validation didn't fail"); + } + }); + + it('should allow urls with scheme for checking origin when the "option.client.webSocketURL" is object', () => { const options = { - public: 'test.host:80', + client: { + webSocketURL: { + host: 'test.host', + }, + }, }; const headers = { origin: 'https://test.host', }; + server = createServer(compiler, options); + if (!server.checkOrigin(headers)) { throw new Error("Validation didn't fail"); } diff --git a/test/server/__snapshots__/Server.test.js.snap.webpack4 b/test/server/__snapshots__/Server.test.js.snap.webpack4 index 9cc203a7a1..009429125f 100644 --- a/test/server/__snapshots__/Server.test.js.snap.webpack4 +++ b/test/server/__snapshots__/Server.test.js.snap.webpack4 @@ -4,9 +4,7 @@ exports[`Server DevServerPlugin add hot option 1`] = ` Array [ Array [ "client", - "index.js?http:", - "0.0.0.0&path=", - "ws&port=8100", + "index.js?ws%3A%2F%2Flocalhost%3A8101%2Fws", ], Array [ "node_modules", @@ -24,9 +22,7 @@ exports[`Server DevServerPlugin add hot-only option 1`] = ` Array [ Array [ "client", - "index.js?http:", - "0.0.0.0&path=", - "ws&port=8100", + "index.js?ws%3A%2F%2Flocalhost%3A8101%2Fws", ], Array [ "node_modules", @@ -44,9 +40,7 @@ exports[`Server DevServerPlugin should create and run server with old parameters Array [ Array [ "client", - "index.js?http:", - "0.0.0.0&path=", - "ws&port=8100", + "index.js?ws%3A%2F%2Flocalhost%3A8101%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 9cc203a7a1..009429125f 100644 --- a/test/server/__snapshots__/Server.test.js.snap.webpack5 +++ b/test/server/__snapshots__/Server.test.js.snap.webpack5 @@ -4,9 +4,7 @@ exports[`Server DevServerPlugin add hot option 1`] = ` Array [ Array [ "client", - "index.js?http:", - "0.0.0.0&path=", - "ws&port=8100", + "index.js?ws%3A%2F%2Flocalhost%3A8101%2Fws", ], Array [ "node_modules", @@ -24,9 +22,7 @@ exports[`Server DevServerPlugin add hot-only option 1`] = ` Array [ Array [ "client", - "index.js?http:", - "0.0.0.0&path=", - "ws&port=8100", + "index.js?ws%3A%2F%2Flocalhost%3A8101%2Fws", ], Array [ "node_modules", @@ -44,9 +40,7 @@ exports[`Server DevServerPlugin should create and run server with old parameters Array [ Array [ "client", - "index.js?http:", - "0.0.0.0&path=", - "ws&port=8100", + "index.js?ws%3A%2F%2Flocalhost%3A8101%2Fws", ], Array [ "node_modules", diff --git a/test/server/open-option.test.js b/test/server/open-option.test.js index 7d229b08de..0f6f42af44 100644 --- a/test/server/open-option.test.js +++ b/test/server/open-option.test.js @@ -35,7 +35,7 @@ describe('"open" option', () => { compiler.hooks.done.tap('webpack-dev-server', () => { server.close(() => { - expect(open).toHaveBeenCalledWith('http://localhost:8117/', { + expect(open).toHaveBeenCalledWith(`http://localhost:${port}/`, { wait: false, }); @@ -58,7 +58,7 @@ describe('"open" option', () => { compiler.hooks.done.tap('webpack-dev-server', () => { server.close(() => { - expect(open).toHaveBeenCalledWith('https://localhost:8117/', { + expect(open).toHaveBeenCalledWith(`https://localhost:${port}/`, { wait: false, }); @@ -72,16 +72,17 @@ describe('"open" option', () => { it("should work with '0.0.0.0' host", (done) => { const compiler = webpack(config); + const host = '0.0.0.0'; const server = createServer(compiler, { - open: true, + host, port, - host: '0.0.0.0', + open: true, static: false, }); compiler.hooks.done.tap('webpack-dev-server', () => { server.close(() => { - expect(open).toHaveBeenCalledWith('http://0.0.0.0:8117/', { + expect(open).toHaveBeenCalledWith(`http://${host}:${port}/`, { wait: false, }); @@ -90,21 +91,22 @@ describe('"open" option', () => { }); compiler.run(() => {}); - server.listen(port, '0.0.0.0'); + server.listen(port, host); }); it("should work with '::' host", (done) => { const compiler = webpack(config); + const host = '::'; const server = createServer(compiler, { - open: true, + host, port, - host: '::', + open: true, static: false, }); compiler.hooks.done.tap('webpack-dev-server', () => { server.close(() => { - expect(open).toHaveBeenCalledWith('http://[::]:8117/', { + expect(open).toHaveBeenCalledWith(`http://[${host}]:${port}/`, { wait: false, }); @@ -113,21 +115,22 @@ describe('"open" option', () => { }); compiler.run(() => {}); - server.listen(port, '::'); + server.listen(port, host); }); it("should work with 'localhost' host", (done) => { const compiler = webpack(config); + const host = 'localhost'; const server = createServer(compiler, { - open: true, + host, port, - host: 'localhost', + open: true, static: false, }); compiler.hooks.done.tap('webpack-dev-server', () => { server.close(() => { - expect(open).toHaveBeenCalledWith('http://localhost:8117/', { + expect(open).toHaveBeenCalledWith(`http://${host}:${port}/`, { wait: false, }); @@ -136,21 +139,22 @@ describe('"open" option', () => { }); compiler.run(() => {}); - server.listen(port, 'localhost'); + server.listen(port, host); }); it("should work with '127.0.0.1' host", (done) => { const compiler = webpack(config); + const host = '127.0.0.1'; const server = createServer(compiler, { - open: true, + host, port, - host: '127.0.0.1', + open: true, static: false, }); compiler.hooks.done.tap('webpack-dev-server', () => { server.close(() => { - expect(open).toHaveBeenCalledWith('http://127.0.0.1:8117/', { + expect(open).toHaveBeenCalledWith(`http://${host}:${port}/`, { wait: false, }); @@ -159,21 +163,22 @@ describe('"open" option', () => { }); compiler.run(() => {}); - server.listen(port, '127.0.0.1'); + server.listen(port, host); }); it("should work with '::1' host", (done) => { const compiler = webpack(config); + const host = '::1'; const server = createServer(compiler, { - open: true, + host, port, - host: '::1', + open: true, static: false, }); compiler.hooks.done.tap('webpack-dev-server', () => { server.close(() => { - expect(open).toHaveBeenCalledWith('http://[::1]:8117/', { + expect(open).toHaveBeenCalledWith(`http://[${host}]:${port}/`, { wait: false, }); @@ -182,21 +187,21 @@ describe('"open" option', () => { }); compiler.run(() => {}); - server.listen(port, '::1'); + server.listen(port, host); }); it(`should work with '${internalIPv4}' host`, (done) => { const compiler = webpack(config); const server = createServer(compiler, { - open: true, - port, host: internalIPv4, + port, + open: true, static: false, }); compiler.hooks.done.tap('webpack-dev-server', () => { server.close(() => { - expect(open).toHaveBeenCalledWith(`http://${internalIPv4}:8117/`, { + expect(open).toHaveBeenCalledWith(`http://${internalIPv4}:${port}/`, { wait: false, }); @@ -235,16 +240,17 @@ describe('"open" option', () => { it('should work with boolean', (done) => { const compiler = webpack(config); + const host = 'localhost'; const server = createServer(compiler, { - open: true, + host, port, - host: 'localhost', + open: true, static: false, }); compiler.hooks.done.tap('webpack-dev-server', () => { server.close(() => { - expect(open).toHaveBeenCalledWith('http://localhost:8117/', { + expect(open).toHaveBeenCalledWith(`http://${host}:${port}/`, { wait: false, }); @@ -253,15 +259,16 @@ describe('"open" option', () => { }); compiler.run(() => {}); - server.listen(port, 'localhost'); + server.listen(port, host); }); it("should work with boolean but don't close with 'false' value", (done) => { const compiler = webpack(config); + const host = 'localhost'; const server = createServer(compiler, { - open: false, + host, port, - host: 'localhost', + open: false, static: false, }); @@ -274,21 +281,22 @@ describe('"open" option', () => { }); compiler.run(() => {}); - server.listen(port, 'localhost'); + server.listen(port, host); }); it('should work with relative string', (done) => { const compiler = webpack(config); + const host = 'localhost'; const server = createServer(compiler, { - open: 'index.html', + host, port, - host: 'localhost', + open: 'index.html', static: false, }); compiler.hooks.done.tap('webpack-dev-server', () => { server.close(() => { - expect(open).toHaveBeenCalledWith('http://localhost:8117/index.html', { + expect(open).toHaveBeenCalledWith(`http://${host}:${port}/index.html`, { wait: false, }); @@ -297,21 +305,22 @@ describe('"open" option', () => { }); compiler.run(() => {}); - server.listen(port, 'localhost'); + server.listen(port, host); }); it('should work with relative string starting with "/"', (done) => { const compiler = webpack(config); + const host = 'localhost'; const server = createServer(compiler, { - open: '/index.html', + host, port, - host: 'localhost', + open: '/index.html', static: false, }); compiler.hooks.done.tap('webpack-dev-server', () => { server.close(() => { - expect(open).toHaveBeenCalledWith('http://localhost:8117/index.html', { + expect(open).toHaveBeenCalledWith(`http://${host}:${port}/index.html`, { wait: false, }); @@ -320,13 +329,14 @@ describe('"open" option', () => { }); compiler.run(() => {}); - server.listen(port, 'localhost'); + server.listen(port, host); }); it('should work with absolute string', (done) => { const compiler = webpack(config); + const host = 'localhost'; const server = createServer(compiler, { - open: 'http://localhost:8117/index.html', + open: `http://${host}:${port}/index.html`, port, host: 'localhost', static: false, @@ -334,7 +344,7 @@ describe('"open" option', () => { compiler.hooks.done.tap('webpack-dev-server', () => { server.close(() => { - expect(open).toHaveBeenCalledWith('http://localhost:8117/index.html', { + expect(open).toHaveBeenCalledWith(`http://${host}:${port}/index.html`, { wait: false, }); @@ -343,15 +353,16 @@ describe('"open" option', () => { }); compiler.run(() => {}); - server.listen(port, 'localhost'); + server.listen(port, host); }); it('should work with multiple relative strings', (done) => { const compiler = webpack(config); + const host = 'localhost'; const server = createServer(compiler, { - open: ['first.html', 'second.html'], - port, host: 'localhost', + port, + open: ['first.html', 'second.html'], static: false, }); @@ -359,14 +370,14 @@ describe('"open" option', () => { server.close(() => { expect(open).toHaveBeenNthCalledWith( 1, - 'http://localhost:8117/first.html', + `http://${host}:${port}/first.html`, { wait: false, } ); expect(open).toHaveBeenNthCalledWith( 2, - 'http://localhost:8117/second.html', + `http://${host}:${port}/second.html`, { wait: false, } @@ -377,18 +388,19 @@ describe('"open" option', () => { }); compiler.run(() => {}); - server.listen(port, 'localhost'); + server.listen(port, host); }); it('should work with multiple absolute strings', (done) => { const compiler = webpack(config); + const host = 'localhost'; const server = createServer(compiler, { + host: 'localhost', + port, open: [ - 'http://localhost:8117/first.html', - 'http://localhost:8117/second.html', + `http://${host}:${port}/first.html`, + `http://${host}:${port}/second.html`, ], - port, - host: 'localhost', static: false, }); @@ -396,14 +408,14 @@ describe('"open" option', () => { server.close(() => { expect(open).toHaveBeenNthCalledWith( 1, - 'http://localhost:8117/first.html', + `http://${host}:${port}/first.html`, { wait: false, } ); expect(open).toHaveBeenNthCalledWith( 2, - 'http://localhost:8117/second.html', + `http://${host}:${port}/second.html`, { wait: false, } @@ -414,21 +426,22 @@ describe('"open" option', () => { }); compiler.run(() => {}); - server.listen(port, 'localhost'); + server.listen(port, host); }); it('should work with empty object', (done) => { const compiler = webpack(config); + const host = 'localhost'; const server = createServer(compiler, { - open: {}, + host, port, - host: 'localhost', + open: {}, static: false, }); compiler.hooks.done.tap('webpack-dev-server', () => { server.close(() => { - expect(open).toHaveBeenCalledWith('http://localhost:8117/', { + expect(open).toHaveBeenCalledWith(`http://${host}:${port}/`, { wait: false, }); @@ -437,23 +450,24 @@ describe('"open" option', () => { }); compiler.run(() => {}); - server.listen(port, 'localhost'); + server.listen(port, host); }); it("should work with object and with the boolean value of 'target' option", (done) => { const compiler = webpack(config); + const host = 'localhost'; const server = createServer(compiler, { + host, + port, open: { target: true, }, - port, - host: 'localhost', static: false, }); compiler.hooks.done.tap('webpack-dev-server', () => { server.close(() => { - expect(open).toHaveBeenCalledWith('http://localhost:8117/', { + expect(open).toHaveBeenCalledWith(`http://${host}:${port}/`, { wait: false, }); @@ -462,23 +476,24 @@ describe('"open" option', () => { }); compiler.run(() => {}); - server.listen(port, 'localhost'); + server.listen(port, host); }); it("should work with object and with the 'target' option", (done) => { const compiler = webpack(config); + const host = 'localhost'; const server = createServer(compiler, { + host, + port, open: { target: 'index.html', }, - port, - host: 'localhost', static: false, }); compiler.hooks.done.tap('webpack-dev-server', () => { server.close(() => { - expect(open).toHaveBeenCalledWith('http://localhost:8117/index.html', { + expect(open).toHaveBeenCalledWith(`http://${host}:${port}/index.html`, { wait: false, }); @@ -487,17 +502,18 @@ describe('"open" option', () => { }); compiler.run(() => {}); - server.listen(port, 'localhost'); + server.listen(port, host); }); it("should work with object and with multiple values of the 'target' option", (done) => { const compiler = webpack(config); + const host = 'localhost'; const server = createServer(compiler, { + host, + port, open: { target: ['first.html', 'second.html'], }, - port, - host: 'localhost', static: false, }); @@ -505,14 +521,14 @@ describe('"open" option', () => { server.close(() => { expect(open).toHaveBeenNthCalledWith( 1, - 'http://localhost:8117/first.html', + `http://${host}:${port}/first.html`, { wait: false, } ); expect(open).toHaveBeenNthCalledWith( 2, - 'http://localhost:8117/second.html', + `http://${host}:${port}/second.html`, { wait: false, } @@ -523,23 +539,24 @@ describe('"open" option', () => { }); compiler.run(() => {}); - server.listen(port, 'localhost'); + server.listen(port, host); }); it("should work with object and with the 'app' option", (done) => { const compiler = webpack(config); + const host = 'localhost'; const server = createServer(compiler, { + host, + port, open: { app: 'google-chrome', }, - port, - host: 'localhost', static: false, }); compiler.hooks.done.tap('webpack-dev-server', () => { server.close(() => { - expect(open).toHaveBeenCalledWith('http://localhost:8117/', { + expect(open).toHaveBeenCalledWith(`http://${host}:${port}/`, { app: { name: 'google-chrome' }, wait: false, }); @@ -549,23 +566,24 @@ describe('"open" option', () => { }); compiler.run(() => {}); - server.listen(port, 'localhost'); + server.listen(port, host); }); it("should work with object and with the 'app' and 'arguments' options", (done) => { const compiler = webpack(config); + const host = 'localhost'; const server = createServer(compiler, { + host, + port, open: { app: { name: 'google-chrome', arguments: ['--incognito'] }, }, - port, - host: 'localhost', static: false, }); compiler.hooks.done.tap('webpack-dev-server', () => { server.close(() => { - expect(open).toHaveBeenCalledWith('http://localhost:8117/', { + expect(open).toHaveBeenCalledWith(`http://${host}:${port}/`, { app: { name: 'google-chrome', arguments: ['--incognito'] }, wait: false, }); @@ -575,24 +593,25 @@ describe('"open" option', () => { }); compiler.run(() => {}); - server.listen(port, 'localhost'); + server.listen(port, host); }); it('should work with object with "target" and "app" options', (done) => { const compiler = webpack(config); + const host = 'localhost'; const server = createServer(compiler, { + host, + port, open: { target: 'index.html', app: 'google-chrome', }, - port, - host: 'localhost', static: false, }); compiler.hooks.done.tap('webpack-dev-server', () => { server.close(() => { - expect(open).toHaveBeenCalledWith('http://localhost:8117/index.html', { + expect(open).toHaveBeenCalledWith(`http://${host}:${port}/index.html`, { app: { name: 'google-chrome' }, wait: false, }); @@ -602,18 +621,19 @@ describe('"open" option', () => { }); compiler.run(() => {}); - server.listen(port, 'localhost'); + server.listen(port, host); }); it("should work with object, with multiple value of the 'target' option and with the 'app' and 'arguments' options", (done) => { const compiler = webpack(config); + const host = 'localhost'; const server = createServer(compiler, { + host, + port, open: { target: ['first.html', 'second.html'], app: { name: 'google-chrome', arguments: ['--incognito'] }, }, - port, - host: 'localhost', static: false, }); @@ -621,7 +641,7 @@ describe('"open" option', () => { server.close(() => { expect(open).toHaveBeenNthCalledWith( 1, - 'http://localhost:8117/first.html', + `http://${host}:${port}/first.html`, { wait: false, app: { name: 'google-chrome', arguments: ['--incognito'] }, @@ -629,7 +649,7 @@ describe('"open" option', () => { ); expect(open).toHaveBeenNthCalledWith( 2, - 'http://localhost:8117/second.html', + `http://${host}:${port}/second.html`, { wait: false, app: { name: 'google-chrome', arguments: ['--incognito'] }, @@ -641,18 +661,19 @@ describe('"open" option', () => { }); compiler.run(() => {}); - server.listen(port, 'localhost'); + server.listen(port, host); }); it("should work with object, with multiple value of the 'target' option (relative and absolute URLs) and with the 'app' option with arguments", (done) => { const compiler = webpack(config); + const host = 'localhost'; const server = createServer(compiler, { + host, + port, open: { - target: ['first.html', 'http://localhost:8117/second.html'], + target: ['first.html', `http://${host}:${port}/second.html`], app: { name: 'google-chrome', arguments: ['--incognito'] }, }, - port, - host: 'localhost', static: false, }); @@ -660,7 +681,7 @@ describe('"open" option', () => { server.close(() => { expect(open).toHaveBeenNthCalledWith( 1, - 'http://localhost:8117/first.html', + `http://${host}:${port}/first.html`, { wait: false, app: { name: 'google-chrome', arguments: ['--incognito'] }, @@ -668,7 +689,7 @@ describe('"open" option', () => { ); expect(open).toHaveBeenNthCalledWith( 2, - 'http://localhost:8117/second.html', + `http://${host}:${port}/second.html`, { wait: false, app: { name: 'google-chrome', arguments: ['--incognito'] }, @@ -680,7 +701,7 @@ describe('"open" option', () => { }); compiler.run(() => {}); - server.listen(port, 'localhost'); + server.listen(port, host); }); it("should log warning when can't open", (done) => { @@ -688,20 +709,19 @@ describe('"open" option', () => { const compiler = webpack(config); const server = createServer(compiler, { - open: true, port, - host: 'localhost', + open: true, static: false, }); const loggerWarnSpy = jest.spyOn(server.logger, 'warn'); compiler.hooks.done.tap('webpack-dev-server', () => { server.close(() => { - expect(open).toHaveBeenCalledWith('http://localhost:8117/', { + expect(open).toHaveBeenCalledWith(`http://localhost:${port}/`, { wait: false, }); expect(loggerWarnSpy).toHaveBeenCalledWith( - 'Unable to open "http://localhost:8117/" page. If you are running in a headless environment, please do not use the "open" option or related flags like "--open", "--open-target", and "--open-app".' + `Unable to open "http://localhost:${port}/" page. If you are running in a headless environment, please do not use the "open" option or related flags like "--open", "--open-target", and "--open-app".` ); loggerWarnSpy.mockRestore(); @@ -726,11 +746,14 @@ describe('"open" option', () => { compiler.hooks.done.tap('webpack-dev-server', () => { server.close(() => { - expect(open).toHaveBeenCalledWith('http://localhost:8117/index.html', { - wait: false, - }); + expect(open).toHaveBeenCalledWith( + `http://localhost:${port}/index.html`, + { + wait: false, + } + ); expect(loggerWarnSpy).toHaveBeenCalledWith( - 'Unable to open "http://localhost:8117/index.html" page. If you are running in a headless environment, please do not use the "open" option or related flags like "--open", "--open-target", and "--open-app".' + `Unable to open "http://localhost:${port}/index.html" page. If you are running in a headless environment, please do not use the "open" option or related flags like "--open", "--open-target", and "--open-app".` ); loggerWarnSpy.mockRestore(); @@ -758,12 +781,15 @@ describe('"open" option', () => { compiler.hooks.done.tap('webpack-dev-server', () => { server.close(() => { - expect(open).toHaveBeenCalledWith('http://localhost:8117/index.html', { - app: { name: 'google-chrome' }, - wait: false, - }); + expect(open).toHaveBeenCalledWith( + `http://localhost:${port}/index.html`, + { + app: { name: 'google-chrome' }, + wait: false, + } + ); expect(loggerWarnSpy).toHaveBeenCalledWith( - 'Unable to open "http://localhost:8117/index.html" page in "google-chrome" app. If you are running in a headless environment, please do not use the "open" option or related flags like "--open", "--open-target", and "--open-app".' + `Unable to open "http://localhost:${port}/index.html" page in "google-chrome" app. If you are running in a headless environment, please do not use the "open" option or related flags like "--open", "--open-target", and "--open-app".` ); loggerWarnSpy.mockRestore(); @@ -794,15 +820,18 @@ describe('"open" option', () => { compiler.hooks.done.tap('webpack-dev-server', () => { server.close(() => { - expect(open).toHaveBeenCalledWith('http://localhost:8117/index.html', { - app: { - name: 'google-chrome', - arguments: ['--incognito', '--new-window'], - }, - wait: false, - }); + expect(open).toHaveBeenCalledWith( + `http://localhost:${port}/index.html`, + { + app: { + name: 'google-chrome', + arguments: ['--incognito', '--new-window'], + }, + wait: false, + } + ); expect(loggerWarnSpy).toHaveBeenCalledWith( - 'Unable to open "http://localhost:8117/index.html" page in "google-chrome" app with "--incognito --new-window" arguments. If you are running in a headless environment, please do not use the "open" option or related flags like "--open", "--open-target", and "--open-app".' + `Unable to open "http://localhost:${port}/index.html" page in "google-chrome" app with "--incognito --new-window" arguments. If you are running in a headless environment, please do not use the "open" option or related flags like "--open", "--open-target", and "--open-app".` ); loggerWarnSpy.mockRestore(); @@ -820,7 +849,7 @@ describe('"open" option', () => { const compiler = webpack(config); const server = createServer(compiler, { open: { - target: ['first.html', 'http://localhost:8117/second.html'], + target: ['first.html', `http://localhost:${port}/second.html`], app: { name: 'google-chrome', arguments: ['--incognito', '--new-window'], @@ -835,7 +864,7 @@ describe('"open" option', () => { server.close(() => { expect(open).toHaveBeenNthCalledWith( 1, - 'http://localhost:8117/first.html', + `http://localhost:${port}/first.html`, { wait: false, app: { @@ -846,7 +875,7 @@ describe('"open" option', () => { ); expect(open).toHaveBeenNthCalledWith( 2, - 'http://localhost:8117/second.html', + `http://localhost:${port}/second.html`, { wait: false, app: { @@ -857,11 +886,11 @@ describe('"open" option', () => { ); expect(loggerWarnSpy).toHaveBeenNthCalledWith( 1, - 'Unable to open "http://localhost:8117/first.html" page in "google-chrome" app with "--incognito --new-window" arguments. If you are running in a headless environment, please do not use the "open" option or related flags like "--open", "--open-target", and "--open-app".' + `Unable to open "http://localhost:${port}/first.html" page in "google-chrome" app with "--incognito --new-window" arguments. If you are running in a headless environment, please do not use the "open" option or related flags like "--open", "--open-target", and "--open-app".` ); expect(loggerWarnSpy).toHaveBeenNthCalledWith( 2, - 'Unable to open "http://localhost:8117/second.html" page in "google-chrome" app with "--incognito --new-window" arguments. If you are running in a headless environment, please do not use the "open" option or related flags like "--open", "--open-target", and "--open-app".' + `Unable to open "http://localhost:${port}/second.html" page in "google-chrome" app with "--incognito --new-window" arguments. If you are running in a headless environment, please do not use the "open" option or related flags like "--open", "--open-target", and "--open-app".` ); loggerWarnSpy.mockRestore(); diff --git a/test/server/servers/__snapshots__/WebsocketServer.test.js.snap.webpack4 b/test/server/servers/__snapshots__/WebsocketServer.test.js.snap.webpack4 index 59934d06dd..c056d6dab1 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:8128"`; +exports[`WebsocketServer should receive connection, send message, and close client 1`] = `"localhost:8127"`; 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 59934d06dd..c056d6dab1 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:8128"`; +exports[`WebsocketServer should receive connection, send message, and close client 1`] = `"localhost:8127"`; exports[`WebsocketServer should receive connection, send message, and close client 2`] = ` Array [ diff --git a/test/server/utils/DevServerPlugin.test.js b/test/server/utils/DevServerPlugin.test.js index 081a7ba2bd..53a4965cfa 100644 --- a/test/server/utils/DevServerPlugin.test.js +++ b/test/server/utils/DevServerPlugin.test.js @@ -27,6 +27,7 @@ describe('DevServerPlugin util', () => { const devServerOptions = { client: { transport: 'sockjs', + webSocketURL: {}, }, webSocketServer: { type: 'sockjs', @@ -79,6 +80,7 @@ describe('DevServerPlugin util', () => { const devServerOptions = { client: { transport: 'sockjs', + webSocketURL: {}, }, webSocketServer: { type: 'sockjs', @@ -122,6 +124,7 @@ describe('DevServerPlugin util', () => { const devServerOptions = { client: { transport: 'sockjs', + webSocketURL: {}, }, webSocketServer: { type: 'sockjs', @@ -143,6 +146,7 @@ describe('DevServerPlugin util', () => { const devServerOptions = { client: { transport: 'sockjs', + webSocketURL: {}, }, webSocketServer: { type: 'sockjs', @@ -168,6 +172,7 @@ describe('DevServerPlugin util', () => { const devServerOptions = { client: { transport: 'sockjs', + webSocketURL: {}, }, webSocketServer: { type: 'sockjs', @@ -193,6 +198,7 @@ describe('DevServerPlugin util', () => { hot: true, client: { transport: 'sockjs', + webSocketURL: {}, }, webSocketServer: { type: 'sockjs', @@ -220,6 +226,7 @@ describe('DevServerPlugin util', () => { hot: true, client: { transport: 'sockjs', + webSocketURL: {}, }, webSocketServer: { type: 'sockjs', @@ -249,6 +256,7 @@ describe('DevServerPlugin util', () => { const devServerOptions = { client: { transport: 'sockjs', + webSocketURL: {}, }, webSocketServer: { type: 'sockjs', diff --git a/test/server/utils/__snapshots__/normalizeOptions.test.js.snap.webpack4 b/test/server/utils/__snapshots__/normalizeOptions.test.js.snap.webpack4 index 41ed9a2d6d..eb5c919c00 100644 --- a/test/server/utils/__snapshots__/normalizeOptions.test.js.snap.webpack4 +++ b/test/server/utils/__snapshots__/normalizeOptions.test.js.snap.webpack4 @@ -6,6 +6,7 @@ Object { "hotEntry": true, "overlay": true, "transport": "/path/to/custom/client/", + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -38,10 +39,12 @@ Object { exports[`normalizeOptions client host and port should set correct options 1`] = ` Object { "client": Object { - "host": "my.host", "hotEntry": true, "overlay": true, - "port": 9000, + "webSocketURL": Object { + "host": "my.host", + "port": 9000, + }, }, "compress": true, "devMiddleware": Object {}, @@ -76,7 +79,9 @@ Object { "client": Object { "hotEntry": true, "overlay": true, - "path": "/custom/path/", + "webSocketURL": Object { + "path": "/custom/path/", + }, }, "compress": true, "devMiddleware": Object {}, @@ -111,7 +116,9 @@ Object { "client": Object { "hotEntry": true, "overlay": true, - "path": "custom/path", + "webSocketURL": Object { + "path": "custom/path", + }, }, "compress": true, "devMiddleware": Object {}, @@ -147,6 +154,7 @@ Object { "hotEntry": true, "overlay": true, "transport": "sockjs", + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -182,6 +190,7 @@ Object { "hotEntry": true, "overlay": true, "transport": "ws", + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -217,6 +226,7 @@ Object { "hotEntry": true, "overlay": true, "transport": "ws", + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -251,6 +261,7 @@ Object { "client": Object { "hotEntry": true, "overlay": true, + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object { @@ -287,6 +298,7 @@ Object { "client": Object { "hotEntry": true, "overlay": true, + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -321,6 +333,7 @@ Object { "client": Object { "hotEntry": false, "overlay": true, + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -355,6 +368,7 @@ Object { "client": Object { "hotEntry": "only", "overlay": true, + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -389,6 +403,7 @@ Object { "client": Object { "hotEntry": true, "overlay": true, + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -423,6 +438,7 @@ Object { "client": Object { "hotEntry": true, "overlay": true, + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -457,6 +473,7 @@ Object { "client": Object { "hotEntry": true, "overlay": true, + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -491,6 +508,7 @@ Object { "client": Object { "hotEntry": true, "overlay": true, + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -527,6 +545,7 @@ Object { "client": Object { "hotEntry": true, "overlay": true, + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -561,6 +580,7 @@ Object { "client": Object { "hotEntry": true, "overlay": true, + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -597,6 +617,7 @@ Object { "client": Object { "hotEntry": true, "overlay": true, + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -633,6 +654,7 @@ Object { "client": Object { "hotEntry": true, "overlay": true, + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -669,6 +691,7 @@ Object { "client": Object { "hotEntry": true, "overlay": true, + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -703,6 +726,7 @@ Object { "client": Object { "hotEntry": true, "overlay": true, + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -748,6 +772,7 @@ Object { "client": Object { "hotEntry": true, "overlay": true, + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -793,6 +818,7 @@ Object { "client": Object { "hotEntry": true, "overlay": true, + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -838,6 +864,7 @@ Object { "client": Object { "hotEntry": true, "overlay": true, + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -872,6 +899,7 @@ Object { "client": Object { "hotEntry": true, "overlay": true, + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -894,6 +922,7 @@ Object { "client": Object { "hotEntry": true, "overlay": true, + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -928,6 +957,7 @@ Object { "client": Object { "hotEntry": true, "overlay": true, + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -962,6 +992,7 @@ Object { "client": Object { "hotEntry": true, "overlay": true, + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -996,6 +1027,7 @@ Object { "client": Object { "hotEntry": true, "overlay": true, + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -1031,6 +1063,7 @@ Object { "client": Object { "hotEntry": true, "overlay": true, + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -1065,6 +1098,7 @@ Object { "client": Object { "hotEntry": true, "overlay": true, + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -1097,6 +1131,7 @@ Object { "client": Object { "hotEntry": true, "overlay": true, + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -1131,6 +1166,7 @@ Object { "client": Object { "hotEntry": true, "overlay": true, + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -1167,6 +1203,7 @@ Object { "client": Object { "hotEntry": true, "overlay": true, + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -1201,6 +1238,7 @@ Object { "client": Object { "hotEntry": true, "overlay": true, + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -1235,6 +1273,7 @@ Object { "client": Object { "hotEntry": true, "overlay": true, + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -1269,6 +1308,7 @@ Object { "client": Object { "hotEntry": true, "overlay": true, + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, diff --git a/test/server/utils/__snapshots__/normalizeOptions.test.js.snap.webpack5 b/test/server/utils/__snapshots__/normalizeOptions.test.js.snap.webpack5 index 41ed9a2d6d..eb5c919c00 100644 --- a/test/server/utils/__snapshots__/normalizeOptions.test.js.snap.webpack5 +++ b/test/server/utils/__snapshots__/normalizeOptions.test.js.snap.webpack5 @@ -6,6 +6,7 @@ Object { "hotEntry": true, "overlay": true, "transport": "/path/to/custom/client/", + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -38,10 +39,12 @@ Object { exports[`normalizeOptions client host and port should set correct options 1`] = ` Object { "client": Object { - "host": "my.host", "hotEntry": true, "overlay": true, - "port": 9000, + "webSocketURL": Object { + "host": "my.host", + "port": 9000, + }, }, "compress": true, "devMiddleware": Object {}, @@ -76,7 +79,9 @@ Object { "client": Object { "hotEntry": true, "overlay": true, - "path": "/custom/path/", + "webSocketURL": Object { + "path": "/custom/path/", + }, }, "compress": true, "devMiddleware": Object {}, @@ -111,7 +116,9 @@ Object { "client": Object { "hotEntry": true, "overlay": true, - "path": "custom/path", + "webSocketURL": Object { + "path": "custom/path", + }, }, "compress": true, "devMiddleware": Object {}, @@ -147,6 +154,7 @@ Object { "hotEntry": true, "overlay": true, "transport": "sockjs", + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -182,6 +190,7 @@ Object { "hotEntry": true, "overlay": true, "transport": "ws", + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -217,6 +226,7 @@ Object { "hotEntry": true, "overlay": true, "transport": "ws", + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -251,6 +261,7 @@ Object { "client": Object { "hotEntry": true, "overlay": true, + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object { @@ -287,6 +298,7 @@ Object { "client": Object { "hotEntry": true, "overlay": true, + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -321,6 +333,7 @@ Object { "client": Object { "hotEntry": false, "overlay": true, + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -355,6 +368,7 @@ Object { "client": Object { "hotEntry": "only", "overlay": true, + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -389,6 +403,7 @@ Object { "client": Object { "hotEntry": true, "overlay": true, + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -423,6 +438,7 @@ Object { "client": Object { "hotEntry": true, "overlay": true, + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -457,6 +473,7 @@ Object { "client": Object { "hotEntry": true, "overlay": true, + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -491,6 +508,7 @@ Object { "client": Object { "hotEntry": true, "overlay": true, + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -527,6 +545,7 @@ Object { "client": Object { "hotEntry": true, "overlay": true, + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -561,6 +580,7 @@ Object { "client": Object { "hotEntry": true, "overlay": true, + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -597,6 +617,7 @@ Object { "client": Object { "hotEntry": true, "overlay": true, + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -633,6 +654,7 @@ Object { "client": Object { "hotEntry": true, "overlay": true, + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -669,6 +691,7 @@ Object { "client": Object { "hotEntry": true, "overlay": true, + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -703,6 +726,7 @@ Object { "client": Object { "hotEntry": true, "overlay": true, + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -748,6 +772,7 @@ Object { "client": Object { "hotEntry": true, "overlay": true, + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -793,6 +818,7 @@ Object { "client": Object { "hotEntry": true, "overlay": true, + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -838,6 +864,7 @@ Object { "client": Object { "hotEntry": true, "overlay": true, + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -872,6 +899,7 @@ Object { "client": Object { "hotEntry": true, "overlay": true, + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -894,6 +922,7 @@ Object { "client": Object { "hotEntry": true, "overlay": true, + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -928,6 +957,7 @@ Object { "client": Object { "hotEntry": true, "overlay": true, + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -962,6 +992,7 @@ Object { "client": Object { "hotEntry": true, "overlay": true, + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -996,6 +1027,7 @@ Object { "client": Object { "hotEntry": true, "overlay": true, + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -1031,6 +1063,7 @@ Object { "client": Object { "hotEntry": true, "overlay": true, + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -1065,6 +1098,7 @@ Object { "client": Object { "hotEntry": true, "overlay": true, + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -1097,6 +1131,7 @@ Object { "client": Object { "hotEntry": true, "overlay": true, + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -1131,6 +1166,7 @@ Object { "client": Object { "hotEntry": true, "overlay": true, + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -1167,6 +1203,7 @@ Object { "client": Object { "hotEntry": true, "overlay": true, + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -1201,6 +1238,7 @@ Object { "client": Object { "hotEntry": true, "overlay": true, + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -1235,6 +1273,7 @@ Object { "client": Object { "hotEntry": true, "overlay": true, + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, @@ -1269,6 +1308,7 @@ Object { "client": Object { "hotEntry": true, "overlay": true, + "webSocketURL": Object {}, }, "compress": true, "devMiddleware": Object {}, diff --git a/test/server/utils/createDomain.test.js b/test/server/utils/createDomain.test.js deleted file mode 100644 index ba28792255..0000000000 --- a/test/server/utils/createDomain.test.js +++ /dev/null @@ -1,115 +0,0 @@ -'use strict'; - -const webpack = require('webpack'); -const Server = require('../../../lib/Server'); -const createDomain = require('../../../lib/utils/createDomain'); -const [port1, port2] = require('../../ports-map').createDomain; -const config = require('./../../fixtures/simple-config/webpack.config'); - -describe('createDomain', () => { - let compiler; - let server; - - beforeEach(() => { - compiler = webpack(config); - }); - - afterEach((done) => { - server.close(done); - }); - - const tests = [ - { - name: 'default', - options: { - host: 'localhost', - port: port1, - }, - expected: [ - `http://localhost:${port1}`, - `http://127.0.0.1:${port1}`, - `http://[::1]:${port1}`, - ], - }, - { - name: 'no host option', - options: { - port: port1, - }, - expected: [`http://0.0.0.0:${port1}`, `http://[::]:${port1}`], - }, - { - name: 'https', - options: { - host: 'localhost', - port: port1, - https: true, - }, - expected: [ - `https://localhost:${port1}`, - `https://127.0.0.1:${port1}`, - `https://[::1]:${port1}`, - ], - timeout: 60000, - }, - { - name: 'override with public', - options: { - host: 'localhost', - port: port1, - public: 'myhost.test', - }, - expected: ['http://myhost.test'], - }, - { - name: 'override with public (port)', - options: { - host: 'localhost', - port: port1, - public: `myhost.test:${port2}`, - }, - expected: [`http://myhost.test:${port2}`], - }, - { - name: 'override with public (protocol)', - options: { - host: 'localhost', - port: port1, - public: 'https://myhost.test', - }, - expected: ['https://myhost.test'], - }, - { - name: 'override with public (protocol + port)', - options: { - host: 'localhost', - port: port1, - public: `https://myhost.test:${port2}`, - }, - expected: [`https://myhost.test:${port2}`], - }, - ]; - - tests.forEach((test) => { - it(`test createDomain '${test.name}'`, (done) => { - const { options, expected } = test; - options.static = false; - - server = new Server(options, compiler); - - server.listen(options.port, options.host, (err) => { - if (err) { - done(err); - } - - const domain = createDomain(options, server.server); - - if (!expected.includes(domain)) { - done(`generated domain ${domain} doesn't match expected ${expected}`); - } else { - done(); - } - }); - }); - }); -}); diff --git a/test/server/utils/normalizeOptions.test.js b/test/server/utils/normalizeOptions.test.js index 855d09141c..cb655712e8 100644 --- a/test/server/utils/normalizeOptions.test.js +++ b/test/server/utils/normalizeOptions.test.js @@ -74,8 +74,10 @@ describe('normalizeOptions', () => { multiCompiler: false, options: { client: { - host: 'my.host', - port: 9000, + webSocketURL: { + host: 'my.host', + port: 9000, + }, }, }, optionsResults: null, @@ -85,7 +87,9 @@ describe('normalizeOptions', () => { multiCompiler: false, options: { client: { - path: '/custom/path/', + webSocketURL: { + path: '/custom/path/', + }, }, }, optionsResults: null, @@ -95,7 +99,9 @@ describe('normalizeOptions', () => { multiCompiler: false, options: { client: { - path: 'custom/path', + webSocketURL: { + path: 'custom/path', + }, }, }, optionsResults: null, diff --git a/test/validate-options.test.js b/test/validate-options.test.js index 32ba0d62a2..9b7455fce3 100644 --- a/test/validate-options.test.js +++ b/test/validate-options.test.js @@ -28,15 +28,6 @@ const tests = { client: { success: [ {}, - { - host: '', - }, - { - path: '', - }, - { - port: '', - }, { logging: 'none', }, @@ -55,22 +46,6 @@ const tests = { { logging: 'verbose', }, - { - host: '', - path: '', - port: 8080, - logging: 'none', - }, - { - host: '', - path: '', - port: '', - }, - { - host: '', - path: '', - port: 'auto', - }, { progress: false, }, @@ -107,17 +82,30 @@ const tests = { { transport: require.resolve('../client/clients/SockJSClient'), }, + { + webSocketURL: 'ws://localhost:8080', + }, + { + webSocketURL: { host: 'localhost' }, + }, + { + webSocketURL: { port: 8080 }, + }, + { + webSocketURL: { path: '' }, + }, + { + webSocketURL: { path: '/my-path/' }, + }, + { + webSocketURL: { host: 'localhost', port: 8080, path: '/my-path/' }, + }, ], failure: [ 'whoops!', { unknownOption: true, }, - { - host: true, - path: '', - port: 8080, - }, { logging: 'whoops!', }, @@ -147,13 +135,22 @@ const tests = { hotEntry: [''], }, { - path: true, + transport: true, + }, + { + webSocketURL: { host: true, path: '', port: 8080 }, }, { - port: true, + webSocketURL: { path: true }, }, { - transport: true, + webSocketURL: { port: true }, + }, + { + webSocketURL: { host: '' }, + }, + { + webSocketURL: { port: '' }, }, ], }, @@ -178,7 +175,7 @@ const tests = { failure: [''], }, host: { - success: ['', 'localhost', null], + success: ['', 'localhost', '::', '::1', null], failure: [false], }, hot: { @@ -269,10 +266,6 @@ const tests = { ], failure: [[], () => {}, false], }, - public: { - success: ['', 'foo', 'auto'], - failure: [false], - }, static: { success: [ 'path',