diff --git a/bin/options.js b/bin/options.js index 3429792aba..5c1cb3159a 100644 --- a/bin/options.js +++ b/bin/options.js @@ -62,17 +62,6 @@ const options = { describe: 'Open default browser with the specified page', requiresArg: true, }, - color: { - type: 'boolean', - alias: 'colors', - default: function supportsColor() { - // Use `require('supports-color').stdout` for supports-color >= 5.0.0. - // See https://github.com/webpack/webpack-dev-server/pull/1555. - return require('supports-color').stdout; - }, - group: DISPLAY_GROUP, - describe: 'Enables/Disables colors on the console', - }, 'client-logging': { type: 'string', group: DISPLAY_GROUP, diff --git a/bin/webpack-dev-server.js b/bin/webpack-dev-server.js index 174a8fa025..dc34a05fe0 100755 --- a/bin/webpack-dev-server.js +++ b/bin/webpack-dev-server.js @@ -15,6 +15,7 @@ const setupExitSignals = require('../lib/utils/setupExitSignals'); const colors = require('../lib/utils/colors'); const processOptions = require('../lib/utils/processOptions'); const getVersions = require('../lib/utils/getVersions'); +const getColorsOption = require('../lib/utils/getColorsOption'); const options = require('./options'); let server; @@ -87,11 +88,14 @@ const config = require(convertArgvPath)(yargs, argv, { function startDevServer(config, options) { let compiler; + const configArr = config instanceof Array ? config : [config]; + const statsColors = getColorsOption(configArr); + try { compiler = webpack(config); } catch (err) { if (err instanceof webpack.WebpackOptionsValidationError) { - console.error(colors.error(options.stats.colors, err.message)); + console.error(colors.error(statsColors, err.message)); // eslint-disable-next-line no-process-exit process.exit(1); } @@ -104,7 +108,7 @@ function startDevServer(config, options) { serverData.server = server; } catch (err) { if (err.name === 'ValidationError') { - console.error(colors.error(options.stats.colors, err.message)); + console.error(colors.error(statsColors, err.message)); // eslint-disable-next-line no-process-exit process.exit(1); } diff --git a/lib/Server.js b/lib/Server.js index 7fefbf6f2d..baa5ab50b2 100644 --- a/lib/Server.js +++ b/lib/Server.js @@ -20,6 +20,8 @@ const compress = require('compression'); const serveIndex = require('serve-index'); const webpack = require('webpack'); const webpackDevMiddleware = require('webpack-dev-middleware'); +const getFilenameFromUrl = require('webpack-dev-middleware/dist/utils/getFilenameFromUrl') + .default; const validateOptions = require('schema-utils'); const isAbsoluteUrl = require('is-absolute-url'); const normalizeOptions = require('./utils/normalizeOptions'); @@ -30,6 +32,9 @@ const createDomain = require('./utils/createDomain'); const runBonjour = require('./utils/runBonjour'); const routes = require('./utils/routes'); const getSocketServerImplementation = require('./utils/getSocketServerImplementation'); +const getCompilerConfigArray = require('./utils/getCompilerConfigArray'); +const getStatsOption = require('./utils/getStatsOption'); +const getColorsOption = require('./utils/getColorsOption'); const schema = require('./options.json'); if (!process.env.WEBPACK_DEV_SERVER) { @@ -146,11 +151,9 @@ class Server { setupDevMiddleware() { // middleware for serving webpack bundle - this.middleware = webpackDevMiddleware( + this.middleware = webpackDevMiddleware.default( this.compiler, - Object.assign({}, this.options, { - logger: this.logger, - }) + this.options.dev ); } @@ -666,12 +669,10 @@ class Server { const suffix = '/'; const uri = `${createDomain(this.options, this.listeningApp)}${suffix}`; - status( - uri, - this.options, - this.logger, - this.options.stats && this.options.stats.colors - ); + const configArr = getCompilerConfigArray(this.compiler); + const colors = getColorsOption(configArr); + + status(uri, this.options, this.logger, colors); } listen(port, hostname, fn) { @@ -732,8 +733,10 @@ class Server { getStats(statsObj) { const stats = Server.DEFAULT_STATS; - if (this.options.stats.warningsFilter) { - stats.warningsFilter = this.options.stats.warningsFilter; + const configArr = getCompilerConfigArray(this.compiler); + const statsOption = getStatsOption(configArr); + if (typeof statsOption === 'object' && statsOption.warningsFilter) { + stats.warningsFilter = statsOption.warningsFilter; } return statsObj.toJson(stats); @@ -861,8 +864,12 @@ class Server { const _path = req.path; try { - const isFile = this.middleware.fileSystem - .statSync(this.middleware.getFilenameFromUrl(`${_path}.js`)) + const filename = getFilenameFromUrl( + this.middleware.context, + `${_path}.js` + ); + const isFile = this.middleware.context.outputFileSystem + .statSync(filename) .isFile(); if (!isFile) { diff --git a/lib/options.json b/lib/options.json index 78eff74c58..82cb4d8869 100644 --- a/lib/options.json +++ b/lib/options.json @@ -75,12 +75,12 @@ } ] }, + "dev": { + "type": "object" + }, "disableHostCheck": { "type": "boolean" }, - "fs": { - "type": "object" - }, "headers": { "type": "object" }, @@ -176,9 +176,6 @@ } ] }, - "index": { - "type": "string" - }, "injectClient": { "anyOf": [ { @@ -202,9 +199,6 @@ "liveReload": { "type": "boolean" }, - "mimeTypes": { - "type": "object" - }, "onAfterSetupMiddleware": { "instanceof": "Function" }, @@ -302,44 +296,18 @@ "public": { "type": "string" }, - "publicPath": { - "type": "string" - }, "requestCert": { "type": "boolean" }, "serveIndex": { "type": "boolean" }, - "serverSideRender": { - "type": "boolean" - }, "socket": { "type": "string" }, "staticOptions": { "type": "object" }, - "stats": { - "anyOf": [ - { - "type": "object" - }, - { - "type": "boolean" - }, - { - "enum": [ - "none", - "errors-only", - "errors-warnings", - "minimal", - "normal", - "verbose" - ] - } - ] - }, "transportMode": { "anyOf": [ { @@ -374,16 +342,6 @@ }, "watchOptions": { "type": "object" - }, - "writeToDisk": { - "anyOf": [ - { - "type": "boolean" - }, - { - "instanceof": "Function" - } - ] } }, "errorMessage": { @@ -393,19 +351,17 @@ "client": "should be {Object} (https://webpack.js.org/configuration/dev-server/#devserverclient)", "compress": "should be {Boolean} (https://webpack.js.org/configuration/dev-server/#devservercompress)", "contentBase": "should be {Number|String|Array} (https://webpack.js.org/configuration/dev-server/#devservercontentbase)", + "dev": "should be {Object} (https://webpack.js.org/configuration/dev-server/#devserverdev-)", "disableHostCheck": "should be {Boolean} (https://webpack.js.org/configuration/dev-server/#devserverdisablehostcheck)", - "fs": "should be {Object} (https://github.com/webpack/webpack-dev-middleware#fs)", - "headers": "should be {Object} (https://webpack.js.org/configuration/dev-server/#devserverheaders-)", + "headers": "should be {Object} (https://webpack.js.org/configuration/dev-server/#devserverheaders)", "historyApiFallback": "should be {Boolean|Object} (https://webpack.js.org/configuration/dev-server/#devserverhistoryapifallback)", "host": "should be {String|Null} (https://webpack.js.org/configuration/dev-server/#devserverhost)", "hot": "should be {Boolean|String} (https://webpack.js.org/configuration/dev-server/#devserverhot)", "http2": "should be {Boolean} (https://webpack.js.org/configuration/dev-server/#devserverhttp2)", "https": "should be {Object|Boolean} (https://webpack.js.org/configuration/dev-server/#devserverhttps)", - "index": "should be {String} (https://webpack.js.org/configuration/dev-server/#devserverindex)", "injectClient": "should be {Boolean|Function} (https://webpack.js.org/configuration/dev-server/#devserverinjectclient)", "injectHot": "should be {Boolean|Function} (https://webpack.js.org/configuration/dev-server/#devserverinjecthot)", - "liveReload": "should be {Boolean} (https://webpack.js.org/configuration/dev-server/#devserverlivereload-)", - "mimeTypes": "should be {Object} (https://webpack.js.org/configuration/dev-server/#devservermimetypes-)", + "liveReload": "should be {Boolean} (https://webpack.js.org/configuration/dev-server/#devserverlivereload)", "onAfterSetupMiddleware": "should be {Function} (https://webpack.js.org/configuration/dev-server/#devserverafter)", "onBeforeSetupMiddleware": "should be {Function} (https://webpack.js.org/configuration/dev-server/#devserverbefore)", "onListening": "should be {Function} (https://webpack.js.org/configuration/dev-server/#onlistening)", @@ -417,19 +373,15 @@ "progress": "should be {Boolean} (https://webpack.js.org/configuration/dev-server/#devserverprogress---cli-only)", "proxy": "should be {Object|Array} (https://webpack.js.org/configuration/dev-server/#devserverproxy)", "public": "should be {String} (https://webpack.js.org/configuration/dev-server/#devserverpublic)", - "publicPath": "should be {String} (https://webpack.js.org/configuration/dev-server/#devserverpublicpath-)", "requestCert": "should be {Boolean}", "contentBasePublicPath": "should be {String|Array} (https://webpack.js.org/configuration/dev-server/#devservercontentbasepublicpath)", "serveIndex": "should be {Boolean} (https://webpack.js.org/configuration/dev-server/#devserverserveindex)", - "serverSideRender": "should be {Boolean} (https://github.com/webpack/webpack-dev-middleware#serversiderender)", "socket": "should be {String} (https://webpack.js.org/configuration/dev-server/#devserversocket)", "staticOptions": "should be {Object} (https://webpack.js.org/configuration/dev-server/#devserverstaticoptions)", - "stats": "should be {Object|Boolean} (https://webpack.js.org/configuration/dev-server/#devserverstats-)", "transportMode": "should be {String|Object} (https://webpack.js.org/configuration/dev-server/#devservertransportmode)", "useLocalIp": "should be {Boolean} (https://webpack.js.org/configuration/dev-server/#devserveruselocalip)", "watchContentBase": "should be {Boolean} (https://webpack.js.org/configuration/dev-server/#devserverwatchcontentbase)", - "watchOptions": "should be {Object} (https://webpack.js.org/configuration/dev-server/#devserverwatchoptions-)", - "writeToDisk": "should be {Boolean|Function} (https://webpack.js.org/configuration/dev-server/#devserverwritetodisk-)" + "watchOptions": "should be {Object} (https://webpack.js.org/configuration/dev-server/#devserverwatchoptions)" } }, "additionalProperties": false diff --git a/lib/utils/createConfig.js b/lib/utils/createConfig.js index b227871c1d..1f23fc0bee 100644 --- a/lib/utils/createConfig.js +++ b/lib/utils/createConfig.js @@ -47,16 +47,18 @@ function createConfig(config, argv, { port }) { options.overlay = argv.overlay; } - if (!options.publicPath) { + options.dev = options.dev || {}; + + if (!options.dev.publicPath) { // eslint-disable-next-line - options.publicPath = + options.dev.publicPath = (firstWpOpt.output && firstWpOpt.output.publicPath) || ''; if ( - !isAbsoluteUrl(String(options.publicPath)) && - options.publicPath[0] !== '/' + !isAbsoluteUrl(String(options.dev.publicPath)) && + options.dev.publicPath[0] !== '/' ) { - options.publicPath = `/${options.publicPath}`; + options.dev.publicPath = `/${options.dev.publicPath}`; } } @@ -111,21 +113,6 @@ function createConfig(config, argv, { port }) { options.watchContentBase = true; } - if (!options.stats) { - options.stats = defaultTo(firstWpOpt.stats, { - cached: false, - cachedAssets: false, - }); - } - - if ( - typeof options.stats === 'object' && - typeof options.stats.colors === 'undefined' && - argv.color - ) { - options.stats = Object.assign({}, options.stats, { colors: argv.color }); - } - if (argv.https) { options.https = true; } diff --git a/lib/utils/getColorsOption.js b/lib/utils/getColorsOption.js new file mode 100644 index 0000000000..75667b49dc --- /dev/null +++ b/lib/utils/getColorsOption.js @@ -0,0 +1,15 @@ +'use strict'; + +const getStatsOption = require('./getStatsOption'); + +function getColorsOption(configArr) { + const statsOption = getStatsOption(configArr); + let colors = false; + if (typeof statsOption === 'object' && statsOption.colors) { + colors = statsOption.colors; + } + + return colors; +} + +module.exports = getColorsOption; diff --git a/lib/utils/getCompilerConfigArray.js b/lib/utils/getCompilerConfigArray.js new file mode 100644 index 0000000000..4cd48fdd50 --- /dev/null +++ b/lib/utils/getCompilerConfigArray.js @@ -0,0 +1,8 @@ +'use strict'; + +function getCompilerConfigArray(compiler) { + const compilers = compiler.compilers ? compiler.compilers : [compiler]; + return compilers.map((comp) => comp.options); +} + +module.exports = getCompilerConfigArray; diff --git a/lib/utils/getStatsOption.js b/lib/utils/getStatsOption.js new file mode 100644 index 0000000000..d0b2ae10f9 --- /dev/null +++ b/lib/utils/getStatsOption.js @@ -0,0 +1,16 @@ +'use strict'; + +function getStatsOption(configArr) { + const isEmptyObject = (val) => + typeof val === 'object' && Object.keys(val).length === 0; + + // in webpack@4 stats will not be defined if not provided, + // but in webpack@5 it will be an empty object + const statsConfig = configArr.find( + (conf) => + typeof conf === 'object' && conf.stats && !isEmptyObject(conf.stats) + ); + return statsConfig ? statsConfig.stats : {}; +} + +module.exports = getStatsOption; diff --git a/lib/utils/normalizeOptions.js b/lib/utils/normalizeOptions.js index b814e11794..da54d079c9 100644 --- a/lib/utils/normalizeOptions.js +++ b/lib/utils/normalizeOptions.js @@ -16,10 +16,6 @@ function normalizeOptions(compiler, options) { : true; options.liveReload = typeof options.liveReload !== 'undefined' ? options.liveReload : true; - options.stats = - options.stats && Object.keys(options.stats).length !== 0 - ? options.stats - : {}; // normalize transportMode option if (typeof options.transportMode === 'undefined') { @@ -49,6 +45,8 @@ function normalizeOptions(compiler, options) { options.client.path = `/${ options.client.path ? options.client.path.replace(/^\/|\/$/g, '') : 'ws' }`; + + options.dev = options.dev || {}; } module.exports = normalizeOptions; diff --git a/lib/utils/routes.js b/lib/utils/routes.js index a6166132c5..ac9055140f 100644 --- a/lib/utils/routes.js +++ b/lib/utils/routes.js @@ -1,7 +1,9 @@ 'use strict'; const { createReadStream } = require('fs'); -const { join } = require('path'); +const { dirname, join } = require('path'); +const getFilenameFromUrl = require('webpack-dev-middleware/dist/utils/getFilenameFromUrl') + .default; const clientBasePath = join(__dirname, '..', '..', 'client'); @@ -34,10 +36,12 @@ function routes(server) { '
' ); - const outputPath = middleware.getFilenameFromUrl(options.publicPath || '/'); - const filesystem = middleware.fileSystem; + const outputPath = dirname( + getFilenameFromUrl(middleware.context, options.dev.publicPath || '/') + ); + const filesystem = middleware.context.outputFileSystem; - writeDirectory(options.publicPath || '/', outputPath); + writeDirectory(options.dev.publicPath || '/', outputPath); res.end(''); diff --git a/package-lock.json b/package-lock.json index 5799af2181..b96c2b3605 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4149,7 +4149,8 @@ "ansi-colors": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz", - "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==" + "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==", + "dev": true }, "ansi-escapes": { "version": "4.3.1", @@ -7604,6 +7605,7 @@ "version": "0.1.7", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", + "dev": true, "requires": { "prr": "~1.0.1" } @@ -9047,8 +9049,7 @@ "fs-monkey": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.1.tgz", - "integrity": "sha512-fcSa+wyTqZa46iWweI7/ZiUfegOZl0SG8+dltIwFXo7+zYU9J9kpS3NB6pZcSlJdhvIwp81Adx2XhZorncxiaA==", - "dev": true + "integrity": "sha512-fcSa+wyTqZa46iWweI7/ZiUfegOZl0SG8+dltIwFXo7+zYU9J9kpS3NB6pZcSlJdhvIwp81Adx2XhZorncxiaA==" }, "fs-readdir-recursive": { "version": "1.1.0", @@ -9655,7 +9656,8 @@ "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true }, "has-symbols": { "version": "1.0.1", @@ -12563,7 +12565,6 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", - "dev": true, "requires": { "p-defer": "^1.0.0" } @@ -12626,7 +12627,6 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.2.0.tgz", "integrity": "sha512-f/xxz2TpdKv6uDn6GtHee8ivFyxwxmPuXatBb1FBwxYNuVpbM3k/Y1Z+vC0mH/dIXXrukYfe3qe5J32Dfjg93A==", - "dev": true, "requires": { "fs-monkey": "1.0.1" } @@ -12635,6 +12635,7 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "dev": true, "requires": { "errno": "^0.1.3", "readable-stream": "^2.0.1" @@ -12644,6 +12645,7 @@ "version": "2.3.7", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -12657,7 +12659,8 @@ "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true } } }, @@ -13810,8 +13813,7 @@ "p-defer": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", - "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", - "dev": true + "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=" }, "p-each-series": { "version": "2.1.0", @@ -14436,7 +14438,8 @@ "prr": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=" + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", + "dev": true }, "psl": { "version": "1.8.0", @@ -16526,6 +16529,7 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "dev": true, "requires": { "has-flag": "^4.0.0" } @@ -17954,33 +17958,33 @@ } }, "webpack-dev-middleware": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.7.2.tgz", - "integrity": "sha512-1xC42LxbYoqLNAhV6YzTYacicgMZQTqRd27Sim9wn5hJrX3I5nxYy1SxSd4+gjUFsz1dQFj+yEe6zEVmSkeJjw==", + "version": "4.0.0-rc.2", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-4.0.0-rc.2.tgz", + "integrity": "sha512-yP04dRrpAVNq1yvRvtkXIP6UCw+hAbWFOgv6dF2rHNYsRYhQuDRVTc09YwbYzyOlmdJzyXxHfNJZ070HVd9cjA==", "requires": { - "memory-fs": "^0.4.1", - "mime": "^2.4.4", - "mkdirp": "^0.5.1", + "mem": "^6.1.0", + "memfs": "^3.2.0", + "mime-types": "^2.1.27", "range-parser": "^1.2.1", - "webpack-log": "^2.0.0" + "schema-utils": "^2.7.0" }, "dependencies": { - "mime": { - "version": "2.4.5", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.5.tgz", - "integrity": "sha512-3hQhEUF027BuxZjQA3s7rIv/7VCQPa27hN9u9g87sEkWaKwQPuXOkVKtOeiyUrnWqTDiOs8Ed2rwg733mB0R5w==" + "mem": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-6.1.0.tgz", + "integrity": "sha512-RlbnLQgRHk5lwqTtpEkBTQ2ll/CG/iB+J4Hy2Wh97PjgZgXgWJWrFF+XXujh3UUVLvR4OOTgZzcWMMwnehlEUg==", + "requires": { + "map-age-cleaner": "^0.1.3", + "mimic-fn": "^3.0.0" + } + }, + "mimic-fn": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-3.0.0.tgz", + "integrity": "sha512-PiVO95TKvhiwgSwg1IdLYlCTdul38yZxZMIcnDSFIBUm4BNZha2qpQ4GpJ++15bHoKDtrW2D69lMfFwdFYtNZQ==" } } }, - "webpack-log": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz", - "integrity": "sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==", - "requires": { - "ansi-colors": "^3.0.0", - "uuid": "^3.3.2" - } - }, "webpack-sources": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", diff --git a/package.json b/package.json index e9744d7477..be83ca3cd3 100644 --- a/package.json +++ b/package.json @@ -59,10 +59,9 @@ "sockjs-client": "1.4.0", "spdy": "^4.0.2", "strip-ansi": "^6.0.0", - "supports-color": "^7.1.0", "url": "^0.11.0", "util": "^0.12.3", - "webpack-dev-middleware": "^3.7.2", + "webpack-dev-middleware": "^4.0.0-rc.2", "ws": "^7.2.5", "yargs": "^13.3.2" }, diff --git a/test/Validation.test.js b/test/Validation.test.js index 0b9d6859bc..dc2c25fe6f 100644 --- a/test/Validation.test.js +++ b/test/Validation.test.js @@ -35,8 +35,8 @@ describe('Validation', () => { config: { hot: 'false' }, }, { - name: 'invalid `writeToDisk` configuration', - config: { writeToDisk: 1 }, + name: 'invalid `injectHot` configuration', + config: { injectHot: 1 }, }, { name: 'invalid `overlay` configuration', diff --git a/test/__snapshots__/Validation.test.js.snap b/test/__snapshots__/Validation.test.js.snap index 2854d7f8ba..9b714cbe1e 100644 --- a/test/__snapshots__/Validation.test.js.snap +++ b/test/__snapshots__/Validation.test.js.snap @@ -14,22 +14,22 @@ exports[`Validation validation should fail validation for invalid \`hot\` config * configuration.hot should be \\"only\\"." `; -exports[`Validation validation should fail validation for invalid \`overlay\` configuration 1`] = ` +exports[`Validation validation should fail validation for invalid \`injectHot\` configuration 1`] = ` "Invalid configuration object. Object has been initialized using a configuration object that does not match the API schema. - - configuration.overlay.errors should be a boolean." + - configuration.injectHot should be one of these: + boolean | function + Details: + * configuration.injectHot should be a boolean. + * configuration.injectHot should be an instance of function." `; -exports[`Validation validation should fail validation for invalid \`writeToDisk\` configuration 1`] = ` +exports[`Validation validation should fail validation for invalid \`overlay\` configuration 1`] = ` "Invalid configuration object. Object has been initialized using a configuration object that does not match the API schema. - - configuration.writeToDisk should be one of these: - boolean | function - Details: - * configuration.writeToDisk should be a boolean. - * configuration.writeToDisk should be an instance of function." + - configuration.overlay.errors should be a boolean." `; exports[`Validation validation should fail validation for no additional properties 1`] = ` "Invalid configuration object. Object has been initialized using a configuration object that does not match the API schema. - configuration has an unknown property 'additional'. These properties are valid: - object { allowedHosts?, bonjour?, client?, compress?, contentBasePublicPath?, contentBase?, disableHostCheck?, fs?, headers?, historyApiFallback?, host?, hot?, http2?, https?, index?, injectClient?, injectHot?, liveReload?, mimeTypes?, onAfterSetupMiddleware?, onBeforeSetupMiddleware?, onListening?, open?, openPage?, overlay?, port?, profile?, progress?, proxy?, public?, publicPath?, requestCert?, serveIndex?, serverSideRender?, socket?, staticOptions?, stats?, transportMode?, useLocalIp?, watchContentBase?, watchOptions?, writeToDisk? }" + object { allowedHosts?, bonjour?, client?, compress?, contentBasePublicPath?, contentBase?, dev?, disableHostCheck?, headers?, historyApiFallback?, host?, hot?, http2?, https?, injectClient?, injectHot?, liveReload?, onAfterSetupMiddleware?, onBeforeSetupMiddleware?, onListening?, open?, openPage?, overlay?, port?, profile?, progress?, proxy?, public?, requestCert?, serveIndex?, socket?, staticOptions?, transportMode?, useLocalIp?, watchContentBase?, watchOptions? }" `; diff --git a/test/cli/cli.test.js b/test/cli/cli.test.js index a44ddf7016..f428fe1cc0 100644 --- a/test/cli/cli.test.js +++ b/test/cli/cli.test.js @@ -90,15 +90,6 @@ describe('CLI', () => { .catch(done); }); - it('--color', (done) => { - testBin('--color') - .then((output) => { - expect(output.stderr).toContain('Project is running at \u001b'); - done(); - }) - .catch(done); - }); - // The Unix socket to listen to (instead of a host). it('--socket', (done) => { const socketPath = join('.', 'webpack.sock'); diff --git a/test/e2e/Client.test.js b/test/e2e/Client.test.js index a629e22562..3438477f13 100644 --- a/test/e2e/Client.test.js +++ b/test/e2e/Client.test.js @@ -60,7 +60,13 @@ describe('reload', () => { }, mode.options ); - testServer.startAwaitingCompilation(reloadConfig, options, done); + + // we need a delay between file writing and the start + // of the compilation due to a bug in webpack@4, as not doing + // so results in the done hook being called repeatedly + setTimeout(() => { + testServer.startAwaitingCompilation(reloadConfig, options, done); + }, 2000); }); afterAll((done) => { diff --git a/test/e2e/Progress.test.js b/test/e2e/Progress.test.js index c6396ff91d..65161136e5 100644 --- a/test/e2e/Progress.test.js +++ b/test/e2e/Progress.test.js @@ -43,7 +43,12 @@ describe('client progress', () => { }, }; - testServer.startAwaitingCompilation(reloadConfig, options, done); + // we need a delay between file writing and the start + // of the compilation due to a bug in webpack@4, as not doing + // so results in the done hook being called repeatedly + setTimeout(() => { + testServer.startAwaitingCompilation(reloadConfig, options, done); + }, 2000); }); afterAll((done) => { diff --git a/test/e2e/Socket-injection.test.js b/test/e2e/Socket-injection.test.js index 2005af6796..f494b84c49 100644 --- a/test/e2e/Socket-injection.test.js +++ b/test/e2e/Socket-injection.test.js @@ -8,7 +8,7 @@ const express = require('express'); const request = require('supertest'); const testServer = require('../helpers/test-server'); const runBrowser = require('../helpers/run-browser'); -const port = require('../ports-map').WebsocketClient; +const port = require('../ports-map').SocketInjection; const config = require('../fixtures/client-config/webpack.config'); const { beforeBrowserCloseDelay } = require('../helpers/puppeteer-constants'); diff --git a/test/fixtures/mime-types-config/file.custom b/test/fixtures/mime-types-config/file.custom new file mode 100644 index 0000000000..9daeafb986 --- /dev/null +++ b/test/fixtures/mime-types-config/file.custom @@ -0,0 +1 @@ +test diff --git a/test/fixtures/mime-types-config/foo.js b/test/fixtures/mime-types-config/foo.js new file mode 100644 index 0000000000..8545da9fb8 --- /dev/null +++ b/test/fixtures/mime-types-config/foo.js @@ -0,0 +1,5 @@ +'use strict'; + +require('./file.custom'); + +console.log('Hey.'); diff --git a/test/fixtures/mime-types-config/webpack.config.js b/test/fixtures/mime-types-config/webpack.config.js new file mode 100644 index 0000000000..26f89175d0 --- /dev/null +++ b/test/fixtures/mime-types-config/webpack.config.js @@ -0,0 +1,31 @@ +'use strict'; + +module.exports = { + mode: 'development', + context: __dirname, + entry: './foo.js', + output: { + path: '/', + }, + node: false, + infrastructureLogging: { + level: 'warn', + }, + module: { + rules: [ + { + test: /\.custom$/, + use: [ + { + loader: 'file-loader', + options: { + name() { + return '[name].[ext]'; + }, + }, + }, + ], + }, + ], + }, +}; diff --git a/test/integration/MultiCompiler.test.js b/test/integration/MultiCompiler.test.js index 5d9cc9c15b..dc472a5a13 100644 --- a/test/integration/MultiCompiler.test.js +++ b/test/integration/MultiCompiler.test.js @@ -20,7 +20,7 @@ describe('multi compiler', () => { it('should handle GET request to bundle', (done) => { req .get('/main.js') - .expect('Content-Type', 'application/javascript; charset=UTF-8') + .expect('Content-Type', 'application/javascript; charset=utf-8') .expect(200, done); }); }); diff --git a/test/integration/UniversalCompiler.test.js b/test/integration/UniversalCompiler.test.js index b8855d55f9..3d07354870 100644 --- a/test/integration/UniversalCompiler.test.js +++ b/test/integration/UniversalCompiler.test.js @@ -19,7 +19,7 @@ describe('universal compiler', () => { it('client bundle should have the inlined the client runtime', (done) => { req .get('/client.js') - .expect('Content-Type', 'application/javascript; charset=UTF-8') + .expect('Content-Type', 'application/javascript; charset=utf-8') .expect(200) .end((err, res) => { if (err) { @@ -36,7 +36,7 @@ describe('universal compiler', () => { // but we'll do it here to check the contents req .get('/server.js') - .expect('Content-Type', 'application/javascript; charset=UTF-8') + .expect('Content-Type', 'application/javascript; charset=utf-8') .expect(200) .end((err, res) => { if (err) { diff --git a/test/options.test.js b/test/options.test.js index b9a1cd230a..46da4a0896 100644 --- a/test/options.test.js +++ b/test/options.test.js @@ -237,17 +237,17 @@ describe('options', () => { success: [0, '.', false], failure: [[1], [false]], }, - disableHostCheck: { - success: [true], - failure: [''], - }, - fs: { + dev: { success: [ { - fs: memfs, + dev: {}, }, ], - failure: [false], + failure: [''], + }, + disableHostCheck: { + success: [true], + failure: [''], }, headers: { success: [{}], @@ -301,10 +301,6 @@ describe('options', () => { }, ], }, - index: { - success: [''], - failure: [false], - }, injectClient: { success: [true, () => {}], failure: [''], @@ -313,10 +309,6 @@ describe('options', () => { success: [true, () => {}], failure: [''], }, - mimeTypes: { - success: [{}], - failure: [false], - }, onListening: { success: [() => {}], failure: [''], @@ -389,10 +381,6 @@ describe('options', () => { success: [''], failure: [false], }, - publicPath: { - success: [''], - failure: [false], - }, requestCert: { success: [true], failure: [''], @@ -401,10 +389,6 @@ describe('options', () => { success: [true], failure: [''], }, - serverSideRender: { - success: [true], - failure: [''], - }, socket: { success: [''], failure: [false], @@ -413,19 +397,6 @@ describe('options', () => { success: [{}], failure: [false], }, - stats: { - success: [ - true, - {}, - 'none', - 'errors-only', - 'errors-warnings', - 'minimal', - 'normal', - 'verbose', - ], - failure: ['whoops!', null], - }, transportMode: { success: [ 'ws', @@ -494,10 +465,6 @@ describe('options', () => { success: [{}], failure: [''], }, - writeToDisk: { - success: [true, () => {}], - failure: [''], - }, }; Object.keys(cases).forEach((key) => { diff --git a/test/ports-map.js b/test/ports-map.js index 843bb91fd4..57676cfc54 100644 --- a/test/ports-map.js +++ b/test/ports-map.js @@ -40,6 +40,8 @@ const portsList = { 'progress-option': 1, 'profile-option': 1, Iframe: 1, + SocketInjection: 1, + 'contentBasePublicPath-option': 1, }; let startPort = 8089; diff --git a/test/server/Server.test.js b/test/server/Server.test.js index b581da4a1a..de0528d0c5 100644 --- a/test/server/Server.test.js +++ b/test/server/Server.test.js @@ -3,7 +3,6 @@ const { relative, sep } = require('path'); const webpack = require('webpack'); const sockjs = require('sockjs/lib/transport'); -const { noop } = require('webpack-dev-middleware/lib/util'); const Server = require('../../lib/Server'); const config = require('../fixtures/simple-config/webpack.config'); const port = require('../ports-map').Server; @@ -105,8 +104,8 @@ describe('Server', () => { }); // issue: https://github.com/webpack/webpack-dev-server/issues/1724 - describe('express.static.mine.types', () => { - it("should success even if mine.types doesn't exist", (done) => { + describe('express.static.mime.types', () => { + it("should success even if mime.types doesn't exist", (done) => { jest.mock('express', () => { const data = jest.requireActual('express'); const { static: st } = data; @@ -140,12 +139,12 @@ describe('Server', () => { describe('Invalidate Callback', () => { describe('Testing callback functions on calling invalidate without callback', () => { - it('should be `noop` (the default callback function)', (done) => { + it('should use default `noop` callback', (done) => { const compiler = webpack(config); const server = new Server(compiler, baseDevConfig); server.invalidate(); - expect(server.middleware.context.callbacks[0]).toBe(noop); + expect(server.middleware.context.callbacks.length).toEqual(1); compiler.hooks.done.tap('webpack-dev-server', () => { server.close(done); @@ -156,7 +155,7 @@ describe('Server', () => { }); describe('Testing callback functions on calling invalidate with callback', () => { - it('should be `callback` function', (done) => { + it('should use `callback` function', (done) => { const compiler = webpack(config); const callback = jest.fn(); const server = new Server(compiler, baseDevConfig); diff --git a/test/server/contentBasePublicPath-option.test.js b/test/server/contentBasePublicPath-option.test.js index 404c0b9437..bf21e96c7e 100644 --- a/test/server/contentBasePublicPath-option.test.js +++ b/test/server/contentBasePublicPath-option.test.js @@ -4,7 +4,7 @@ const path = require('path'); const request = require('supertest'); const testServer = require('../helpers/test-server'); const config = require('../fixtures/contentbase-config/webpack.config'); -const port = require('../ports-map')['contentBase-option']; +const port = require('../ports-map')['contentBasePublicPath-option']; const contentBasePublic = path.resolve( __dirname, diff --git a/test/server/headers-option.test.js b/test/server/headers-option.test.js index caf4de79d7..6faad95412 100644 --- a/test/server/headers-option.test.js +++ b/test/server/headers-option.test.js @@ -54,4 +54,27 @@ describe('headers option', () => { req.get('/main').expect('X-Bar', expected).expect(200, done); }); }); + + describe('dev middleware headers take precedence for dev middleware output files', () => { + beforeAll((done) => { + server = testServer.start( + config, + { + headers: { 'X-Foo': '1' }, + dev: { + headers: { 'X-Foo': '2' }, + }, + port, + }, + done + ); + req = request(server.app); + }); + + afterAll(testServer.close); + + it('GET request with headers', (done) => { + req.get('/main.js').expect('X-Foo', '2').expect(200, done); + }); + }); }); diff --git a/test/server/mimeTypes-option.test.js b/test/server/mimeTypes-option.test.js index 662007dadd..c7f26b54c7 100644 --- a/test/server/mimeTypes-option.test.js +++ b/test/server/mimeTypes-option.test.js @@ -2,38 +2,41 @@ const request = require('supertest'); const testServer = require('../helpers/test-server'); -const config = require('../fixtures/simple-config/webpack.config'); +const config = require('../fixtures/mime-types-config/webpack.config'); const port = require('../ports-map')['mineTypes-option']; describe('mimeTypes option', () => { - describe('as an object', () => { - afterEach(testServer.close); - - it('should remapping mime type without force should throw an error', () => { - expect(() => { - testServer.start(config, { - mimeTypes: { 'application/octet-stream': ['js'] }, - port, - }); - }).toThrow(/Attempt to change mapping for/); - }); + describe('as an object with a remapped type', () => { + let server; + let req; - it('should remapping mime type with force should not throw an error', (done) => { - testServer.start( + beforeAll((done) => { + server = testServer.start( config, { - mimeTypes: { - typeMap: { 'application/octet-stream': ['js'] }, - force: true, + dev: { + mimeTypes: { + js: 'application/octet-stream', + }, }, port, }, done ); + req = request(server.app); + }); + + afterAll(testServer.close); + + it('requests file with different js mime type', (done) => { + req + .get('/main.js') + .expect('Content-Type', 'application/octet-stream') + .expect(200, done); }); }); - describe('as an object with force option', () => { + describe('as an object with a custom type', () => { let server; let req; @@ -41,9 +44,10 @@ describe('mimeTypes option', () => { server = testServer.start( config, { - mimeTypes: { - typeMap: { 'application/octet-stream': ['js'] }, - force: true, + dev: { + mimeTypes: { + custom: 'text/html', + }, }, port, }, @@ -54,10 +58,10 @@ describe('mimeTypes option', () => { afterAll(testServer.close); - it('request to bundle file with modified mime type', (done) => { + it('requests file with custom mime type', (done) => { req - .get('/main.js') - .expect('Content-Type', /application\/octet-stream/) + .get('/file.custom') + .expect('Content-Type', 'text/html; charset=utf-8') .expect(200, done); }); }); diff --git a/test/server/stats-option.test.js b/test/server/stats-option.test.js index 0de16746ac..e6cefa3c64 100644 --- a/test/server/stats-option.test.js +++ b/test/server/stats-option.test.js @@ -21,8 +21,8 @@ describe('stats option', () => { return allStats.reduce((p, stats) => { return p.then(() => { return new Promise((resolve) => { - const compiler = webpack(config); - const server = new Server(compiler, { stats, port }); + const compiler = webpack(Object.assign({}, config, { stats })); + const server = new Server(compiler, { port }); compiler.hooks.done.tap('webpack-dev-server', (s) => { expect(Object.keys(server.getStats(s)).sort()).toMatchSnapshot(); @@ -38,9 +38,12 @@ describe('stats option', () => { }); it('should respect warningsFilter', (done) => { - const compiler = webpack(config); + const compiler = webpack( + Object.assign({}, config, { + stats: { warningsFilter: 'test' }, + }) + ); const server = new Server(compiler, { - stats: { warningsFilter: 'test' }, port, }); diff --git a/test/server/utils/__snapshots__/createConfig.test.js.snap b/test/server/utils/__snapshots__/createConfig.test.js.snap index 6da3d696aa..05dfd4490a 100644 --- a/test/server/utils/__snapshots__/createConfig.test.js.snap +++ b/test/server/utils/__snapshots__/createConfig.test.js.snap @@ -6,13 +6,11 @@ Object { ".host.com", "host2.com", ], + "dev": Object { + "publicPath": "/", + }, "hot": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -22,39 +20,33 @@ Object { ".host.com", "host2.com", ], + "dev": Object { + "publicPath": "/", + }, "hot": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; exports[`createConfig bonjour option (devServer config) 1`] = ` Object { "bonjour": true, + "dev": Object { + "publicPath": "/", + }, "hot": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; exports[`createConfig bonjour option 1`] = ` Object { "bonjour": true, + "dev": Object { + "publicPath": "/", + }, "hot": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -63,13 +55,11 @@ Object { "client": Object { "logging": "none", }, + "dev": Object { + "publicPath": "/", + }, "hot": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -78,13 +68,11 @@ Object { "client": Object { "logging": "none", }, + "dev": Object { + "publicPath": "/", + }, "hot": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -93,39 +81,33 @@ Object { "client": Object { "logging": "none", }, + "dev": Object { + "publicPath": "/", + }, "hot": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; exports[`createConfig compress option (in devServer config) 1`] = ` Object { "compress": true, + "dev": Object { + "publicPath": "/", + }, "hot": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; exports[`createConfig compress option 1`] = ` Object { "compress": true, + "dev": Object { + "publicPath": "/", + }, "hot": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -135,298 +117,255 @@ Object { "assets", "static", ], + "dev": Object { + "publicPath": "/", + }, "hot": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; exports[`createConfig contentBase option (boolean) 1`] = ` Object { "contentBase": false, + "dev": Object { + "publicPath": "/", + }, "hot": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; exports[`createConfig contentBase option (string) (in devServer config) 1`] = ` Object { "contentBase": "assets", + "dev": Object { + "publicPath": "/", + }, "hot": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; exports[`createConfig contentBase option (string) 1`] = ` Object { "contentBase": "assets", + "dev": Object { + "publicPath": "/", + }, "hot": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; exports[`createConfig disableHostCheck option (in devServer config) 1`] = ` Object { + "dev": Object { + "publicPath": "/", + }, "disableHostCheck": true, "hot": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; exports[`createConfig disableHostCheck option 1`] = ` Object { + "dev": Object { + "publicPath": "/", + }, "disableHostCheck": true, "hot": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; exports[`createConfig historyApiFallback option (in devServer config) 1`] = ` Object { + "dev": Object { + "publicPath": "/", + }, "historyApiFallback": true, "hot": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; exports[`createConfig historyApiFallback option 1`] = ` Object { + "dev": Object { + "publicPath": "/", + }, "historyApiFallback": true, "hot": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; exports[`createConfig host option (devServer config) 1`] = ` Object { + "dev": Object { + "publicPath": "/", + }, "host": "example.dev", "hot": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; exports[`createConfig host option (localhost) 1`] = ` Object { + "dev": Object { + "publicPath": "/", + }, "host": "localhost", "hot": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; exports[`createConfig host option (null) 1`] = ` Object { + "dev": Object { + "publicPath": "/", + }, "hot": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; exports[`createConfig host option (specify for CLI and devServer config) 1`] = ` Object { + "dev": Object { + "publicPath": "/", + }, "host": "other.dev", "hot": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; exports[`createConfig host option (undefined) 1`] = ` Object { + "dev": Object { + "publicPath": "/", + }, "hot": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; exports[`createConfig host option 1`] = ` Object { + "dev": Object { + "publicPath": "/", + }, "host": "example.dev", "hot": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; exports[`createConfig hot only option (in devServer config) 1`] = ` Object { + "dev": Object { + "publicPath": "/", + }, "hot": "only", "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; exports[`createConfig hot only option 1`] = ` Object { + "dev": Object { + "publicPath": "/", + }, "hot": "only", "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; exports[`createConfig hot option (false) (in devServer config) 1`] = ` Object { + "dev": Object { + "publicPath": "/", + }, "hot": false, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; exports[`createConfig hot option (false) 1`] = ` Object { + "dev": Object { + "publicPath": "/", + }, "hot": false, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; exports[`createConfig hot option (true) (in devServer config) 1`] = ` Object { + "dev": Object { + "publicPath": "/", + }, "hot": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; exports[`createConfig hot option (true) 1`] = ` Object { + "dev": Object { + "publicPath": "/", + }, "hot": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; exports[`createConfig http2 option (in devServer config) 1`] = ` Object { + "dev": Object { + "publicPath": "/", + }, "hot": true, "http2": true, "https": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; exports[`createConfig http2 option 1`] = ` Object { + "dev": Object { + "publicPath": "/", + }, "hot": true, "http2": true, "https": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; exports[`createConfig https option (in devServer config) 1`] = ` Object { + "dev": Object { + "publicPath": "/", + }, "hot": true, "https": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; exports[`createConfig https option (in devServer config) 2`] = ` Object { + "dev": Object { + "publicPath": "/", + }, "hot": true, "https": Object { "ca": Object { @@ -435,67 +374,57 @@ Object { }, }, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; exports[`createConfig https option 1`] = ` Object { + "dev": Object { + "publicPath": "/", + }, "hot": true, "https": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; exports[`createConfig https option 2`] = ` Object { + "dev": Object { + "publicPath": "/", + }, "hot": true, "https": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; exports[`createConfig info option 1`] = ` Object { + "dev": Object { + "publicPath": "/", + }, "hot": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; exports[`createConfig liveReload option 1`] = ` Object { + "dev": Object { + "publicPath": "/", + }, "hot": true, "liveReload": false, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; exports[`createConfig mimeTypes option - with force 1`] = ` Object { + "dev": Object { + "publicPath": "/", + }, "hot": true, "mimeTypes": Object { "force": true, @@ -506,16 +435,14 @@ Object { }, }, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; exports[`createConfig mimeTypes option 1`] = ` Object { + "dev": Object { + "publicPath": "/", + }, "hot": true, "mimeTypes": Object { "text/html": Array [ @@ -523,57 +450,49 @@ Object { ], }, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; exports[`createConfig onListening option 1`] = ` Object { + "dev": Object { + "publicPath": "/", + }, "hot": true, "onListening": [Function], "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; exports[`createConfig open option (boolean) (in devServer config) 1`] = ` Object { + "dev": Object { + "publicPath": "/", + }, "hot": true, "open": true, "openPage": "", "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; exports[`createConfig open option (boolean) 1`] = ` Object { + "dev": Object { + "publicPath": "/", + }, "hot": true, "open": true, "openPage": "", "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; exports[`createConfig open option (object) 1`] = ` Object { + "dev": Object { + "publicPath": "/", + }, "hot": true, "open": Object { "app": Array [ @@ -583,30 +502,26 @@ Object { }, "openPage": "", "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; exports[`createConfig open option (string) 1`] = ` Object { + "dev": Object { + "publicPath": "/", + }, "hot": true, "open": "Google Chrome", "openPage": "", "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; exports[`createConfig openPage multiple option (in devServer config) 1`] = ` Object { + "dev": Object { + "publicPath": "/", + }, "hot": true, "open": true, "openPage": Array [ @@ -614,444 +529,305 @@ Object { "/different/page2", ], "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; exports[`createConfig openPage option (in devServer config) 1`] = ` Object { + "dev": Object { + "publicPath": "/", + }, "hot": true, "open": true, "openPage": "/different/page", "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; exports[`createConfig openPage option 1`] = ` Object { + "dev": Object { + "publicPath": "/", + }, "hot": true, "open": true, "openPage": Array [ "/different/page", ], "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; exports[`createConfig overlay option (in devServer config) 1`] = ` Object { + "dev": Object { + "publicPath": "/", + }, "hot": true, "overlay": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; exports[`createConfig overlay option 1`] = ` Object { + "dev": Object { + "publicPath": "/", + }, "hot": true, "overlay": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; exports[`createConfig port option (difference) 1`] = ` Object { + "dev": Object { + "publicPath": "/", + }, "hot": true, "port": 7070, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; exports[`createConfig port option (same) (null) 1`] = ` Object { + "dev": Object { + "publicPath": "/", + }, "hot": true, "port": null, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; exports[`createConfig port option (same) (string) 1`] = ` Object { + "dev": Object { + "publicPath": "/", + }, "hot": true, "port": "9090", - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; exports[`createConfig port option (same) (undefined) 1`] = ` Object { + "dev": Object { + "publicPath": "/", + }, "hot": true, "port": undefined, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; exports[`createConfig port option (same) 1`] = ` Object { + "dev": Object { + "publicPath": "/", + }, "hot": true, "port": 9090, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; exports[`createConfig profile option 1`] = ` Object { + "dev": Object { + "publicPath": "/", + }, "hot": true, "port": 8080, "profile": "profile", - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; exports[`createConfig progress option (devServer config) 1`] = ` Object { + "dev": Object { + "publicPath": "/", + }, "hot": true, "port": 8080, "progress": true, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; exports[`createConfig progress option 1`] = ` Object { + "dev": Object { + "publicPath": "/", + }, "hot": true, "port": 8080, "progress": true, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; exports[`createConfig public option (devServer config) 1`] = ` Object { + "dev": Object { + "publicPath": "/", + }, "hot": true, "port": 8080, "public": true, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; exports[`createConfig public option 1`] = ` Object { + "dev": Object { + "publicPath": "/", + }, "hot": true, "port": 8080, "public": true, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; exports[`createConfig publicPath option (not specify) 1`] = ` Object { + "dev": Object { + "publicPath": "/", + }, "hot": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; exports[`createConfig publicPath option (path in devServer option) 1`] = ` Object { + "dev": Object { + "publicPath": "/assets/", + }, "hot": true, "port": 8080, - "publicPath": "/assets/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; exports[`createConfig publicPath option (path in output option) 1`] = ` Object { + "dev": Object { + "publicPath": "/assets/", + }, "hot": true, "port": 8080, - "publicPath": "/assets/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; exports[`createConfig publicPath option (path without starting slash in output option) 1`] = ` Object { + "dev": Object { + "publicPath": "/assets/", + }, "hot": true, "port": 8080, - "publicPath": "/assets/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; exports[`createConfig publicPath option (url in devServer option) 1`] = ` Object { + "dev": Object { + "publicPath": "http://localhost:8080/assets/", + }, "hot": true, "port": 8080, - "publicPath": "http://localhost:8080/assets/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; exports[`createConfig publicPath option (url in output option) 1`] = ` Object { + "dev": Object { + "publicPath": "http://localhost:8080/assets/", + }, "hot": true, "port": 8080, - "publicPath": "http://localhost:8080/assets/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; exports[`createConfig simple 1`] = ` Object { + "dev": Object { + "publicPath": "/", + }, "hot": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; exports[`createConfig socket option (devServer config) 1`] = ` Object { - "hot": true, - "port": 8080, - "publicPath": "/", - "socket": "socket", - "stats": Object { - "cached": false, - "cachedAssets": false, + "dev": Object { + "publicPath": "/", }, -} -`; - -exports[`createConfig socket option 1`] = ` -Object { "hot": true, "port": 8080, - "publicPath": "/", "socket": "socket", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; -exports[`createConfig stats option (colors) 1`] = ` +exports[`createConfig socket option 1`] = ` Object { - "hot": true, - "port": 8080, - "publicPath": "/", - "stats": Object { - "colors": true, - "errors": true, + "dev": Object { + "publicPath": "/", }, -} -`; - -exports[`createConfig stats option 1`] = ` -Object { "hot": true, "port": 8080, - "publicPath": "/", - "stats": "errors-only", -} -`; - -exports[`createConfig use webpack stats 1`] = ` -Object { - "clientLogging": "_clientLogging", - "compress": "_compress", - "contentBase": "_contentBase", - "disableHostCheck": "_disableHostCheck", - "historyApiFallback": "_historyApiFallback", - "host": "_foo", - "hot": true, - "https": "_https", - "open": "_open", - "openPage": "_openPage", - "port": "_port", - "progress": "_progress", - "public": "_public", - "publicPath": "_publicPath", - "socket": "_socket", - "stats": Object { - "assetsSort": "size", - }, - "useLocalIp": "_useLocalIp", - "watchContentBase": "_watchContentBase", -} -`; - -exports[`createConfig use webpack stats 2`] = ` -Object { - "devServer": Object { - "clientLogging": "_clientLogging", - "compress": "_compress", - "contentBase": "_contentBase", - "disableHostCheck": "_disableHostCheck", - "historyApiFallback": "_historyApiFallback", - "host": "_foo", - "hot": true, - "https": "_https", - "open": "_open", - "openPage": "_openPage", - "port": "_port", - "progress": "_progress", - "public": "_public", - "publicPath": "_publicPath", - "socket": "_socket", - "stats": Object { - "assetsSort": "size", - }, - "useLocalIp": "_useLocalIp", - "watchContentBase": "_watchContentBase", - }, - "entry": "./app.js", - "mode": "development", - "stats": Object { - "assetsSort": "size", - }, + "socket": "socket", } `; exports[`createConfig useLocalIp option (in devServer config) 1`] = ` Object { + "dev": Object { + "publicPath": "/", + }, "hot": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, "useLocalIp": true, } `; exports[`createConfig useLocalIp option 1`] = ` Object { + "dev": Object { + "publicPath": "/", + }, "hot": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, "useLocalIp": true, } `; exports[`createConfig watchContentBase option (in devServer config) 1`] = ` Object { + "dev": Object { + "publicPath": "/", + }, "hot": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, "watchContentBase": true, } `; exports[`createConfig watchContentBase option 1`] = ` Object { + "dev": Object { + "publicPath": "/", + }, "hot": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, "watchContentBase": true, } `; exports[`createConfig watchOptions option (in devServer config) 1`] = ` Object { + "dev": Object { + "publicPath": "/", + }, "hot": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, "watchOptions": Object { "poll": true, }, @@ -1060,13 +836,11 @@ Object { exports[`createConfig watchOptions option (in output config) 1`] = ` Object { + "dev": Object { + "publicPath": "/", + }, "hot": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, "watchOptions": Object { "poll": true, }, diff --git a/test/server/utils/__snapshots__/normalizeOptions.test.js.snap b/test/server/utils/__snapshots__/normalizeOptions.test.js.snap index 0b28d00f93..4a039e0aae 100644 --- a/test/server/utils/__snapshots__/normalizeOptions.test.js.snap +++ b/test/server/utils/__snapshots__/normalizeOptions.test.js.snap @@ -8,10 +8,10 @@ Object { "port": 9000, }, "contentBasePublicPath": "/", + "dev": Object {}, "hot": true, "liveReload": true, "serveIndex": true, - "stats": Object {}, "transportMode": Object { "client": "ws", "server": "ws", @@ -26,10 +26,10 @@ Object { "path": "/custom/path", }, "contentBasePublicPath": "/", + "dev": Object {}, "hot": true, "liveReload": true, "serveIndex": true, - "stats": Object {}, "transportMode": Object { "client": "ws", "server": "ws", @@ -44,10 +44,10 @@ Object { "path": "/custom/path", }, "contentBasePublicPath": "/", + "dev": Object {}, "hot": true, "liveReload": true, "serveIndex": true, - "stats": Object {}, "transportMode": Object { "client": "ws", "server": "ws", @@ -66,10 +66,10 @@ Object { "/path/to/dist2", ], "contentBasePublicPath": "/", + "dev": Object {}, "hot": true, "liveReload": true, "serveIndex": true, - "stats": Object {}, "transportMode": Object { "client": "ws", "server": "ws", @@ -85,10 +85,10 @@ Object { }, "contentBase": "/path/to/dist", "contentBasePublicPath": "/", + "dev": Object {}, "hot": true, "liveReload": true, "serveIndex": true, - "stats": Object {}, "transportMode": Object { "client": "ws", "server": "ws", @@ -103,10 +103,30 @@ Object { "path": "/ws", }, "contentBasePublicPath": "/content-base-public-path", + "dev": Object {}, + "hot": true, + "liveReload": true, + "serveIndex": true, + "transportMode": Object { + "client": "ws", + "server": "ws", + }, + "watchOptions": Object {}, +} +`; + +exports[`normalizeOptions dev is set should set correct options 1`] = ` +Object { + "client": Object { + "path": "/ws", + }, + "contentBasePublicPath": "/", + "dev": Object { + "serverSideRender": true, + }, "hot": true, "liveReload": true, "serveIndex": true, - "stats": Object {}, "transportMode": Object { "client": "ws", "server": "ws", @@ -121,10 +141,10 @@ Object { "path": "/ws", }, "contentBasePublicPath": "/", + "dev": Object {}, "hot": false, "liveReload": true, "serveIndex": true, - "stats": Object {}, "transportMode": Object { "client": "ws", "server": "ws", @@ -139,10 +159,10 @@ Object { "path": "/ws", }, "contentBasePublicPath": "/", + "dev": Object {}, "hot": "only", "liveReload": true, "serveIndex": true, - "stats": Object {}, "transportMode": Object { "client": "ws", "server": "ws", @@ -157,10 +177,10 @@ Object { "path": "/ws", }, "contentBasePublicPath": "/", + "dev": Object {}, "hot": true, "liveReload": true, "serveIndex": true, - "stats": Object {}, "transportMode": Object { "client": "ws", "server": "ws", @@ -175,10 +195,10 @@ Object { "path": "/ws", }, "contentBasePublicPath": "/", + "dev": Object {}, "hot": true, "liveReload": false, "serveIndex": true, - "stats": Object {}, "transportMode": Object { "client": "ws", "server": "ws", @@ -193,10 +213,10 @@ Object { "path": "/ws", }, "contentBasePublicPath": "/", + "dev": Object {}, "hot": true, "liveReload": true, "serveIndex": true, - "stats": Object {}, "transportMode": Object { "client": "ws", "server": "ws", @@ -211,10 +231,10 @@ Object { "path": "/ws", }, "contentBasePublicPath": "/", + "dev": Object {}, "hot": true, "liveReload": true, "serveIndex": true, - "stats": Object {}, "transportMode": Object { "client": "ws", "server": "ws", @@ -229,10 +249,10 @@ Object { "path": "/ws", }, "contentBasePublicPath": "/", + "dev": Object {}, "hot": true, "liveReload": true, "serveIndex": true, - "stats": Object {}, "transportMode": Object { "client": "/path/to/custom/client/", "server": "ws", @@ -247,10 +267,10 @@ Object { "path": "/ws", }, "contentBasePublicPath": "/", + "dev": Object {}, "hot": true, "liveReload": true, "serveIndex": true, - "stats": Object {}, "transportMode": Object { "client": "ws", "server": [Function], @@ -265,10 +285,10 @@ Object { "path": "/ws", }, "contentBasePublicPath": "/", + "dev": Object {}, "hot": true, "liveReload": true, "serveIndex": true, - "stats": Object {}, "transportMode": Object { "client": "ws", "server": "/path/to/custom/server/", @@ -283,10 +303,10 @@ Object { "path": "/ws", }, "contentBasePublicPath": "/", + "dev": Object {}, "hot": true, "liveReload": true, "serveIndex": true, - "stats": Object {}, "transportMode": Object { "client": "sockjs", "server": "sockjs", @@ -301,10 +321,10 @@ Object { "path": "/ws", }, "contentBasePublicPath": "/", + "dev": Object {}, "hot": true, "liveReload": true, "serveIndex": true, - "stats": Object {}, "transportMode": Object { "client": "ws", "server": "ws", @@ -319,10 +339,10 @@ Object { "path": "/ws", }, "contentBasePublicPath": "/", + "dev": Object {}, "hot": true, "liveReload": true, "serveIndex": true, - "stats": Object {}, "transportMode": Object { "client": "ws", "server": "ws", @@ -337,10 +357,10 @@ Object { "path": "/ws", }, "contentBasePublicPath": "/", + "dev": Object {}, "hot": true, "liveReload": true, "serveIndex": true, - "stats": Object {}, "transportMode": Object { "client": "ws", "server": "ws", diff --git a/test/server/utils/createConfig.test.js b/test/server/utils/createConfig.test.js index 0e9b62d39d..89b317e145 100644 --- a/test/server/utils/createConfig.test.js +++ b/test/server/utils/createConfig.test.js @@ -3,7 +3,6 @@ const path = require('path'); const createConfig = require('../../../lib/utils/createConfig'); const webpackConfig = require('./../../fixtures/schema/webpack.config.simple'); -const webpackConfigNoStats = require('./../../fixtures/schema/webpack.config.no-dev-stats'); const argv = { port: 8080, @@ -217,7 +216,11 @@ describe('createConfig', () => { it('publicPath option (path in devServer option)', () => { const config = createConfig( Object.assign({}, webpackConfig, { - devServer: { publicPath: '/assets/' }, + devServer: { + dev: { + publicPath: '/assets/', + }, + }, }), argv, { port: 8080 } @@ -229,7 +232,11 @@ describe('createConfig', () => { it('publicPath option (url in devServer option)', () => { const config = createConfig( Object.assign({}, webpackConfig, { - devServer: { publicPath: 'http://localhost:8080/assets/' }, + devServer: { + dev: { + publicPath: 'http://localhost:8080/assets/', + }, + }, }), argv, { port: 8080 } @@ -480,30 +487,6 @@ describe('createConfig', () => { expect(config).toMatchSnapshot(); }); - it('stats option', () => { - const config = createConfig( - Object.assign({}, webpackConfig, { - devServer: { stats: 'errors-only' }, - }), - argv, - { port: 8080 } - ); - - expect(config).toMatchSnapshot(); - }); - - it('stats option (colors)', () => { - const config = createConfig( - Object.assign({}, webpackConfig, { - devServer: { stats: { errors: true } }, - }), - Object.assign({}, argv, { color: true }), - { port: 8080 } - ); - - expect(config).toMatchSnapshot(); - }); - it('info option', () => { const config = createConfig( webpackConfig, @@ -827,13 +810,6 @@ describe('createConfig', () => { expect(config).toMatchSnapshot(); }); - it('use webpack stats', () => { - expect( - createConfig(webpackConfigNoStats, argv, { port: 8080 }) - ).toMatchSnapshot(); - expect(webpackConfigNoStats).toMatchSnapshot(); - }); - it('onListening option', () => { const config = createConfig( Object.assign({}, webpackConfig, { diff --git a/test/server/utils/getColorsOption.test.js b/test/server/utils/getColorsOption.test.js new file mode 100644 index 0000000000..87e7a36913 --- /dev/null +++ b/test/server/utils/getColorsOption.test.js @@ -0,0 +1,96 @@ +'use strict'; + +const getColorsOption = require('../../../lib/utils/getColorsOption'); + +describe('getColorsOption', () => { + it('should return false for empty config array', () => { + expect(getColorsOption([])).toEqual(false); + }); + + it('should return false for config array with no colors option', () => { + expect( + getColorsOption([ + { + entry: './index.js', + }, + ]) + ).toEqual(false); + }); + + it('should return false for config array with stats string but no colors option', () => { + expect( + getColorsOption([ + { + stats: 'verbose', + }, + ]) + ).toEqual(false); + }); + + it('should return false for config array with stats object but no colors option', () => { + expect( + getColorsOption([ + { + stats: { + cached: false, + }, + }, + ]) + ).toEqual(false); + }); + + it('should return false for first stats option with no colors option', () => { + expect( + getColorsOption([ + { + stats: { + cached: false, + }, + }, + { + stats: { + colors: true, + }, + }, + ]) + ).toEqual(false); + }); + + it('should return true for first stats option that has true colors option', () => { + expect( + getColorsOption([ + { + stats: { + colors: true, + }, + }, + { + stats: { + cached: false, + }, + }, + ]) + ).toEqual(true); + }); + + it('should return object for first stats option that has object colors option', () => { + expect( + getColorsOption([ + { + stats: { + colors: { + green: '\u001b[32m', + }, + }, + }, + { + stats: { + cached: false, + }, + }, + ]) + ).toEqual({ + green: '\u001b[32m', + }); + }); +}); diff --git a/test/server/utils/getCompilerConfigArray.test.js b/test/server/utils/getCompilerConfigArray.test.js new file mode 100644 index 0000000000..4595b94341 --- /dev/null +++ b/test/server/utils/getCompilerConfigArray.test.js @@ -0,0 +1,47 @@ +'use strict'; + +const webpack = require('webpack'); +const getCompilerConfigArray = require('../../../lib/utils/getCompilerConfigArray'); +const isWebpack5 = require('../../helpers/isWebpack5'); + +describe('getCompilerConfigArray', () => { + it('should get config array from single compiler', () => { + const compiler = webpack({ + stats: 'errors-only', + }); + const configArr = getCompilerConfigArray(compiler); + expect(configArr.length).toEqual(1); + const stats = configArr[0].stats; + if (isWebpack5) { + expect(stats).toEqual({ + preset: 'errors-only', + }); + } else { + expect(stats).toEqual('errors-only'); + } + }); + + it('should get config array from multi compiler', () => { + const compiler = webpack([ + { + stats: 'none', + }, + { + stats: 'errors-only', + }, + ]); + const configArr = getCompilerConfigArray(compiler); + expect(configArr.length).toEqual(2); + if (isWebpack5) { + expect(configArr[0].stats).toEqual({ + preset: 'none', + }); + expect(configArr[1].stats).toEqual({ + preset: 'errors-only', + }); + } else { + expect(configArr[0].stats).toEqual('none'); + expect(configArr[1].stats).toEqual('errors-only'); + } + }); +}); diff --git a/test/server/utils/getStatsOption.test.js b/test/server/utils/getStatsOption.test.js new file mode 100644 index 0000000000..a0ca3f646a --- /dev/null +++ b/test/server/utils/getStatsOption.test.js @@ -0,0 +1,92 @@ +'use strict'; + +const webpack = require('webpack'); +const getCompilerConfigArray = require('../../../lib/utils/getCompilerConfigArray'); +const getStatsOption = require('../../../lib/utils/getStatsOption'); +const isWebpack5 = require('../../helpers/isWebpack5'); + +describe('getStatsOption', () => { + it('should return empty stats object for empty array', () => { + expect(getStatsOption([])).toEqual({}); + }); + + it('should return empty stats object for array with no stats option', () => { + expect( + getStatsOption([ + { + entry: './index.js', + }, + ]) + ).toEqual({}); + }); + + it('should return stats string for array with stats string', () => { + expect( + getStatsOption([ + { + stats: 'verbose', + }, + ]) + ).toEqual('verbose'); + }); + + it('should return stats object for array with stats object', () => { + expect( + getStatsOption([ + { + stats: { + colors: { + green: '\u001b[32m', + }, + }, + }, + ]) + ).toEqual({ + colors: { + green: '\u001b[32m', + }, + }); + }); + + it('should return first existing stats option', () => { + expect( + getStatsOption([ + { + entry: './index.js', + }, + { + stats: 'verbose', + }, + { + stats: 'none', + }, + ]) + ).toEqual('verbose'); + }); + + it('should find first stats option in webpack config', () => { + const compiler = webpack([ + { + entry: './index.js', + }, + { + stats: {}, + }, + { + stats: 'errors-only', + }, + { + stats: 'none', + }, + ]); + const configArr = getCompilerConfigArray(compiler); + const statsOption = getStatsOption(configArr); + if (isWebpack5) { + expect(statsOption).toEqual({ + preset: 'errors-only', + }); + } else { + expect(statsOption).toEqual('errors-only'); + } + }); +}); diff --git a/test/server/utils/normalizeOptions.test.js b/test/server/utils/normalizeOptions.test.js index 57474cb8ab..70b8594409 100644 --- a/test/server/utils/normalizeOptions.test.js +++ b/test/server/utils/normalizeOptions.test.js @@ -173,6 +173,16 @@ describe('normalizeOptions', () => { }, optionsResults: null, }, + { + title: 'dev is set', + multiCompiler: false, + options: { + dev: { + serverSideRender: true, + }, + }, + optionsResults: null, + }, ]; cases.forEach((data) => {