From 73d3feced18b4e3708f958707326a6642a594cf2 Mon Sep 17 00:00:00 2001 From: Alexander Akait <4567934+alexander-akait@users.noreply.github.com> Date: Wed, 6 Jan 2021 18:06:11 +0300 Subject: [PATCH] =?UTF-8?q?fix:=20respect=20`--stats`,=20`--color`=20and?= =?UTF-8?q?=20`--no-color`=20option=20for=20serve=20c=E2=80=A6=20(#2312)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 +- .../__snapshots__/startDevServer.test.ts.snap | 89 --------- .../serve/__tests__/startDevServer.test.ts | 173 ------------------ packages/serve/src/index.ts | 2 +- packages/serve/src/startDevServer.ts | 54 ++++-- packages/serve/src/types.ts | 5 +- .../webpack-cli/__tests__/resolveArgs.test.js | 21 --- packages/webpack-cli/lib/webpack-cli.js | 124 +++++++------ test/core-flags/stats-flags.test.js | 16 +- test/serve/basic/serve-basic.test.js | 19 +- .../config-no/no-stats-with-config.test.js | 17 +- test/stats/config/index.js | 5 +- test/stats/config/package.json | 8 - test/stats/config/stats.test.js | 43 ++++- test/stats/config/webpack.config.js | 2 +- test/stats/flags/index.js | 5 +- test/stats/flags/package.json | 8 - test/stats/flags/stats.test.js | 42 ++++- yarn.lock | 13 +- 19 files changed, 234 insertions(+), 414 deletions(-) delete mode 100644 packages/serve/__tests__/__snapshots__/startDevServer.test.ts.snap delete mode 100644 packages/serve/__tests__/startDevServer.test.ts delete mode 100644 test/stats/config/package.json delete mode 100644 test/stats/flags/package.json diff --git a/package.json b/package.json index e890c28c1d7..2da9bb158d7 100644 --- a/package.json +++ b/package.json @@ -90,7 +90,7 @@ "strip-ansi": "^6.0.0", "ts-jest": "^26.4.3", "typescript": "^3.9.7", - "webpack": "^5.11.0", + "webpack": "^5.11.1", "webpack-bundle-analyzer": "^4.3.0", "webpack-dev-server": "^3.11.1", "yeoman-test": "^2.7.0" diff --git a/packages/serve/__tests__/__snapshots__/startDevServer.test.ts.snap b/packages/serve/__tests__/__snapshots__/startDevServer.test.ts.snap deleted file mode 100644 index ad76801f1da..00000000000 --- a/packages/serve/__tests__/__snapshots__/startDevServer.test.ts.snap +++ /dev/null @@ -1,89 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`startDevServer should set default port and host if not provided 1`] = ` -Object { - "host": "localhost", - "port": 8080, - "publicPath": "/", -} -`; - -exports[`startDevServer should set default port and host if not provided 2`] = ` -Array [ - 8080, - "localhost", - [Function], -] -`; - -exports[`startDevServer should start dev server correctly for multi compiler with 1 devServer config 1`] = ` -Object { - "bonjour": true, - "host": "my.host", - "hot": true, - "port": 9000, - "progress": true, - "publicPath": "/", -} -`; - -exports[`startDevServer should start dev server correctly for multi compiler with 1 devServer config 2`] = ` -Array [ - 9000, - "my.host", - [Function], -] -`; - -exports[`startDevServer should start dev server correctly for single compiler 1`] = ` -Object { - "bonjour": true, - "host": "my.host", - "hot": true, - "port": 9000, - "progress": true, - "publicPath": "/", -} -`; - -exports[`startDevServer should start dev server correctly for single compiler 2`] = ` -Array [ - 9000, - "my.host", - [Function], -] -`; - -exports[`startDevServer should start dev servers correctly for multi compiler with 2 devServer configs 1`] = ` -Object { - "host": "localhost", - "port": 9000, - "progress": true, - "publicPath": "/", -} -`; - -exports[`startDevServer should start dev servers correctly for multi compiler with 2 devServer configs 2`] = ` -Object { - "host": "localhost", - "port": 9001, - "progress": true, - "publicPath": "/", -} -`; - -exports[`startDevServer should start dev servers correctly for multi compiler with 2 devServer configs 3`] = ` -Array [ - 9000, - "localhost", - [Function], -] -`; - -exports[`startDevServer should start dev servers correctly for multi compiler with 2 devServer configs 4`] = ` -Array [ - 9001, - "localhost", - [Function], -] -`; diff --git a/packages/serve/__tests__/startDevServer.test.ts b/packages/serve/__tests__/startDevServer.test.ts deleted file mode 100644 index e6377ca2ec1..00000000000 --- a/packages/serve/__tests__/startDevServer.test.ts +++ /dev/null @@ -1,173 +0,0 @@ -'use strict'; - -import startDevServer from '../src/startDevServer'; - -jest.mock('webpack-dev-server/lib/Server'); - -describe('startDevServer', () => { - // eslint-disable-next-line @typescript-eslint/no-var-requires, node/no-extraneous-require - const webpack = require('webpack'); - // eslint-disable-next-line @typescript-eslint/no-var-requires, node/no-extraneous-require - const DevServer = require('webpack-dev-server/lib/Server'); - - beforeEach(() => { - DevServer.mockClear(); - }); - - it('should start dev server correctly for single compiler', async () => { - const config = { - devServer: { - port: 9000, - hot: false, - bonjour: true, - }, - }; - const compiler = webpack(config); - - const servers = await startDevServer( - compiler, - { - host: 'my.host', - hot: true, - progress: true, - }, - console, - ); - - expect(servers.length).toEqual(1); - expect(servers).toEqual(DevServer.mock.instances); - - // this is the constructor - expect(DevServer.mock.calls.length).toEqual(1); - // the 2nd argument is the options - expect(DevServer.mock.calls[0][1]).toMatchSnapshot(); - - // the server should listen on correct host and port - expect(DevServer.mock.instances[0].listen.mock.calls.length).toEqual(1); - expect(DevServer.mock.instances[0].listen.mock.calls[0]).toMatchSnapshot(); - }); - - it('should set default port and host if not provided', async () => { - const config = { - devServer: {}, - }; - const compiler = webpack(config); - - const servers = await startDevServer(compiler, {}, console); - - expect(servers.length).toEqual(1); - expect(servers).toEqual(DevServer.mock.instances); - - // this is the constructor - expect(DevServer.mock.calls.length).toEqual(1); - // the 2nd argument is the options - expect(DevServer.mock.calls[0][1]).toMatchSnapshot(); - - // the server should listen on correct host and port - expect(DevServer.mock.instances[0].listen.mock.calls.length).toEqual(1); - expect(DevServer.mock.instances[0].listen.mock.calls[0]).toMatchSnapshot(); - }); - - it('should start dev server correctly for multi compiler with 1 devServer config', async () => { - const config = [ - { - devServer: { - port: 9000, - hot: false, - bonjour: true, - }, - }, - {}, - ]; - const compiler = webpack(config); - - const servers = await startDevServer( - compiler, - { - host: 'my.host', - hot: true, - progress: true, - }, - console, - ); - - expect(servers.length).toEqual(1); - expect(servers).toEqual(DevServer.mock.instances); - - // this is the constructor - expect(DevServer.mock.calls.length).toEqual(1); - // the 2nd argument is the options - expect(DevServer.mock.calls[0][1]).toMatchSnapshot(); - - // the server should listen on correct host and port - expect(DevServer.mock.instances[0].listen.mock.calls.length).toEqual(1); - expect(DevServer.mock.instances[0].listen.mock.calls[0]).toMatchSnapshot(); - }); - - it('should start dev servers correctly for multi compiler with 2 devServer configs', async () => { - const config = [ - { - devServer: { - port: 9000, - // here to show that it will be overridden - progress: false, - }, - }, - { - devServer: { - port: 9001, - }, - }, - ]; - const compiler = webpack(config); - - const servers = await startDevServer( - compiler, - { - // this progress CLI flag should override progress: false above - progress: true, - }, - console, - ); - - // there are 2 devServer configs, so both are run - expect(servers.length).toEqual(2); - expect(servers).toEqual(DevServer.mock.instances); - - // this is the constructor - expect(DevServer.mock.calls.length).toEqual(2); - // the 2nd argument is the options - expect(DevServer.mock.calls[0][1]).toMatchSnapshot(); - expect(DevServer.mock.calls[1][1]).toMatchSnapshot(); - - // both servers should listen on correct host and port - - expect(DevServer.mock.instances[0].listen.mock.calls.length).toEqual(1); - expect(DevServer.mock.instances[0].listen.mock.calls[0]).toMatchSnapshot(); - - expect(DevServer.mock.instances[1].listen.mock.calls.length).toEqual(1); - expect(DevServer.mock.instances[1].listen.mock.calls[0]).toMatchSnapshot(); - }); - - it('should handle 2 multi compiler devServer configs with conflicting ports', async () => { - await expect(async () => { - const config = [ - { - devServer: { - port: 9000, - }, - }, - { - devServer: { - port: 9000, - }, - }, - ]; - const compiler = webpack(config); - - await startDevServer(compiler, {}, console); - }).rejects.toThrow( - 'Unique ports must be specified for each devServer option in your webpack configuration. Alternatively, run only 1 devServer config using the --config-name flag to specify your desired config.', - ); - }); -}); diff --git a/packages/serve/src/index.ts b/packages/serve/src/index.ts index 5108eb93924..2c9e0186bb3 100644 --- a/packages/serve/src/index.ts +++ b/packages/serve/src/index.ts @@ -108,7 +108,7 @@ class ServeCommand { } try { - servers = await startDevServer(compiler, devServerOptions, logger); + servers = await startDevServer(compiler, devServerOptions, options, logger); } catch (error) { if (error.name === 'ValidationError') { logger.error(error.message); diff --git a/packages/serve/src/startDevServer.ts b/packages/serve/src/startDevServer.ts index dd5065248ca..f6a825654df 100644 --- a/packages/serve/src/startDevServer.ts +++ b/packages/serve/src/startDevServer.ts @@ -5,12 +5,13 @@ import { devServerOptionsType } from './types'; * Starts the devServer * * @param {Object} compiler - a webpack compiler - * @param {Object} cliOptions - devServer args + * @param {Object} devServerCliOptions - dev server CLI options + * @param {Object} cliOptions - CLI options * @param {Object} logger - logger * * @returns {Object[]} array of resulting servers */ -export default async function startDevServer(compiler, cliOptions, logger): Promise { +export default async function startDevServer(compiler, devServerCliOptions, cliOptions, logger): Promise { let devServerVersion, Server, findPort; try { @@ -25,15 +26,15 @@ export default async function startDevServer(compiler, cliOptions, logger): Prom process.exit(2); } - const mergeOptions = (cliOptions: devServerOptionsType, devServerOptions: devServerOptionsType): devServerOptionsType => { + const mergeOptions = (devServerOptions: devServerOptionsType, devServerCliOptions: devServerOptionsType): devServerOptionsType => { // CLI options should take precedence over devServer options, // and CLI options should have no default values included - const options = { ...devServerOptions, ...cliOptions }; + const options = { ...devServerOptions, ...devServerCliOptions }; - if (devServerOptions.client && cliOptions.client) { + if (devServerOptions.client && devServerCliOptions.client) { // the user could set some client options in their devServer config, // then also specify client options on the CLI - options.client = { ...devServerOptions.client, ...cliOptions.client }; + options.client = { ...devServerOptions.client, ...devServerCliOptions.client }; } return options; @@ -59,23 +60,48 @@ export default async function startDevServer(compiler, cliOptions, logger): Prom const devServersOptions = []; for (const compilerWithDevServerOption of compilersWithDevServerOption) { - const options = mergeOptions(cliOptions, compilerWithDevServerOption.options.devServer || {}); + const options = mergeOptions(compilerWithDevServerOption.options.devServer || {}, devServerCliOptions); if (isDevServer4) { options.port = await findPort(options.port); options.client = options.client || {}; options.client.port = options.client.port || options.port; } else { - if (!options.publicPath) { - options.publicPath = - typeof compilerWithDevServerOption.options.output.publicPath === 'undefined' || - compilerWithDevServerOption.options.output.publicPath === 'auto' - ? '/' - : compilerWithDevServerOption.options.output.publicPath; - } + const getPublicPathOption = () => { + const normalizePublicPath = (publicPath) => (typeof publicPath === 'undefined' || publicPath === 'auto' ? '/' : publicPath); + + if (cliOptions.outputPublicPath) { + return normalizePublicPath(compilerWithDevServerOption.options.output.publicPath); + } + + // webpack-dev-server@3 + if (options.publicPath) { + return normalizePublicPath(options.publicPath); + } + + // webpack-dev-server@4 + if (options.dev && options.dev.publicPath) { + return normalizePublicPath(options.dev.publicPath); + } + + return normalizePublicPath(compilerWithDevServerOption.options.output.publicPath); + }; + const getStatsOption = () => { + if (cliOptions.stats) { + return compilerWithDevServerOption.options.stats; + } + + if (options.stats) { + return options.stats; + } + + return compilerWithDevServerOption.options.stats; + }; options.host = options.host || 'localhost'; options.port = options.port || 8080; + options.stats = getStatsOption(); + options.publicPath = getPublicPathOption(); } if (options.port) { diff --git a/packages/serve/src/types.ts b/packages/serve/src/types.ts index f4a1b276fd0..1876f21a990 100644 --- a/packages/serve/src/types.ts +++ b/packages/serve/src/types.ts @@ -2,7 +2,8 @@ export type devServerOptionsType = { bonjour?: boolean; client?: devServerClientOptions; compress?: boolean; - dev?: object; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + dev?: Record; firewall?: boolean | string[]; headers?: object; historyApiFallback?: boolean | object; @@ -28,6 +29,8 @@ export type devServerOptionsType = { transportMode?: object | string; useLocalIp?: boolean; publicPath?: undefined; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + stats?: any; }; type devServerClientOptions = { diff --git a/packages/webpack-cli/__tests__/resolveArgs.test.js b/packages/webpack-cli/__tests__/resolveArgs.test.js index c57bc89589d..67a1a0feeb1 100644 --- a/packages/webpack-cli/__tests__/resolveArgs.test.js +++ b/packages/webpack-cli/__tests__/resolveArgs.test.js @@ -1,14 +1,7 @@ const { resolve } = require('path'); -const { version } = require('webpack'); const webpackCLI = require('../lib/webpack-cli'); const targetValues = ['web', 'webworker', 'node', 'async-node', 'node-webkit', 'electron-main', 'electron-renderer', 'electron-preload']; -const statsPresets = ['normal', 'detailed', 'errors-only', 'errors-warnings', 'minimal', 'verbose', 'none']; - -if (version.startsWith('5')) { - statsPresets.push('summary'); -} - const applyOptions = new webpackCLI().applyOptions; describe('BasicResolver', () => { @@ -76,12 +69,6 @@ describe('BasicResolver', () => { expect(result.options).toMatchObject({ mode: 'development' }); }); - it('should assign stats correctly', async () => { - const result = await applyOptions({ options: {} }, { stats: 'errors-warnings' }); - - expect(result.options.stats).toEqual('errors-warnings'); - }); - targetValues.map((option) => { it(`should handle ${option} option`, async () => { const result = await applyOptions({ options: {} }, { target: option }); @@ -89,12 +76,4 @@ describe('BasicResolver', () => { expect(result.options.target).toEqual(option); }); }); - - statsPresets.map((preset) => { - it(`should handle ${preset} preset`, async () => { - const result = await applyOptions({ options: {} }, { stats: preset }); - - expect(result.options.stats).toEqual(preset); - }); - }); }); diff --git a/packages/webpack-cli/lib/webpack-cli.js b/packages/webpack-cli/lib/webpack-cli.js index 1401bafca9a..e8e83ca8128 100644 --- a/packages/webpack-cli/lib/webpack-cli.js +++ b/packages/webpack-cli/lib/webpack-cli.js @@ -314,10 +314,6 @@ class WebpackCLI { this.makeCommand(bundleCommandOptions, this.getBuiltInOptions(), async (program) => { const options = program.opts(); - if (typeof colorFromArguments !== 'undefined') { - options.color = colorFromArguments; - } - if (program.args.length > 0) { const possibleCommands = [].concat([bundleCommandOptions.name]).concat(program.args); @@ -449,21 +445,18 @@ class WebpackCLI { }); // Default `--color` and `--no-color` options - // TODO doesn't work with `webpack serve` (never work, need fix), `--stats` doesn't work too, other options are fine - let colorFromArguments; - this.program.option('--color', 'Enable colors on console.'); this.program.on('option:color', function () { const { color } = this.opts(); - colorFromArguments = color; + coloretteOptions.changed = true; coloretteOptions.enabled = color; }); this.program.option('--no-color', 'Disable colors on console.'); this.program.on('option:no-color', function () { const { color } = this.opts(); - colorFromArguments = color; + coloretteOptions.changed = true; coloretteOptions.enabled = color; }); @@ -1111,6 +1104,63 @@ class WebpackCLI { ? config.options.map((options) => processLegacyArguments(options)) : processLegacyArguments(config.options); + // Apply `stats` and `stats.colors` options + const applyStatsColors = (configOptions) => { + // TODO remove after drop webpack@4 + const statsForWebpack4 = webpack.Stats && webpack.Stats.presetToOptions; + + if (statsForWebpack4) { + if (typeof configOptions.stats === 'undefined') { + configOptions.stats = {}; + } else if (typeof configOptions.stats === 'boolean' || typeof configOptions.stats === 'string') { + if ( + typeof configOptions.stats === 'string' && + configOptions.stats !== 'none' && + configOptions.stats !== 'verbose' && + configOptions.stats !== 'detailed' && + configOptions.stats !== 'minimal' && + configOptions.stats !== 'errors-only' && + configOptions.stats !== 'errors-warnings' + ) { + return configOptions; + } + + configOptions.stats = webpack.Stats.presetToOptions(configOptions.stats); + } + } else { + if (typeof configOptions.stats === 'undefined') { + configOptions.stats = { preset: 'normal' }; + } else if (typeof configOptions.stats === 'boolean') { + configOptions.stats = configOptions.stats ? { preset: 'normal' } : { preset: 'none' }; + } else if (typeof configOptions.stats === 'string') { + configOptions.stats = { preset: configOptions.stats }; + } + } + + let colors; + + // From arguments + if (typeof coloretteOptions.changed !== 'undefined') { + colors = Boolean(coloretteOptions.enabled); + } + // From stats + else if (typeof configOptions.stats.colors !== 'undefined') { + colors = configOptions.stats.colors; + } + // Default + else { + colors = Boolean(coloretteOptions.enabled); + } + + configOptions.stats.colors = colors; + + return configOptions; + }; + + config.options = Array.isArray(config.options) + ? config.options.map((options) => applyStatsColors(options)) + : applyStatsColors(config.options); + return config; } @@ -1210,53 +1260,19 @@ class WebpackCLI { process.exitCode = 1; } - // TODO remove after drop webpack@4 - const statsForWebpack4 = webpack.Stats && webpack.Stats.presetToOptions; - - const getStatsOptions = (stats) => { - if (statsForWebpack4) { - if (!stats) { - stats = {}; - } else if (typeof stats === 'boolean' || typeof stats === 'string') { - stats = webpack.Stats.presetToOptions(stats); - } - } - - let colors; - - // From arguments - if (typeof options.color !== 'undefined') { - colors = options.color; - } - // From stats - else if (typeof stats.colors !== 'undefined') { - colors = stats.colors; - } - // Default - else { - colors = coloretteOptions.enabled; - } - - stats.colors = colors; - - return stats; - }; - if (!compiler) { return; } - const foundStats = compiler.compilers - ? { - children: compiler.compilers.map((compiler) => - getStatsOptions(compiler.options ? compiler.options.stats : undefined), - ), - } - : getStatsOptions(compiler.options ? compiler.options.stats : undefined); + const statsOptions = compiler.compilers + ? { children: compiler.compilers.map((compiler) => (compiler.options ? compiler.options.stats : undefined)) } + : compiler.options + ? compiler.options.stats + : undefined; // TODO webpack@4 doesn't support `{ children: [{ colors: true }, { colors: true }] }` for stats - if (statsForWebpack4 && compiler.compilers) { - foundStats.colors = foundStats.children.some((child) => child.colors); + if (compiler.compilers && !compiler.compilers.find(oneOfCompiler => oneOfCompiler.webpack)) { + statsOptions.colors = statsOptions.children.some((child) => child.colors); } if (options.json) { @@ -1266,13 +1282,13 @@ class WebpackCLI { }; if (options.json === true) { - createJsonStringifyStream(stats.toJson(foundStats)) + createJsonStringifyStream(stats.toJson(statsOptions)) .on('error', handleWriteError) .pipe(process.stdout) .on('error', handleWriteError) .on('close', () => process.stdout.write('\n')); } else { - createJsonStringifyStream(stats.toJson(foundStats)) + createJsonStringifyStream(stats.toJson(statsOptions)) .on('error', handleWriteError) .pipe(createWriteStream(options.json)) .on('error', handleWriteError) @@ -1282,11 +1298,11 @@ class WebpackCLI { ); } } else { - const printedStats = stats.toString(foundStats); + const printedStats = stats.toString(statsOptions); // Avoid extra empty line when `stats: 'none'` if (printedStats) { - logger.raw(`${stats.toString(foundStats)}`); + logger.raw(printedStats); } } }; diff --git a/test/core-flags/stats-flags.test.js b/test/core-flags/stats-flags.test.js index 904e5f774da..3dccbbea5b5 100644 --- a/test/core-flags/stats-flags.test.js +++ b/test/core-flags/stats-flags.test.js @@ -20,9 +20,9 @@ describe('stats config related flag', () => { if (flag.name.includes('reset')) { const option = propName.split('Reset')[0]; - expect(stdout).toContain(`stats: { ${option}: [] }`); + expect(stdout).toContain(`${option}: []`); } else { - expect(stdout).toContain(`stats: { ${propName}: true }`); + expect(stdout).toContain(`${propName}: true`); } }); @@ -32,7 +32,7 @@ describe('stats config related flag', () => { expect(exitCode).toBe(0); expect(stderr).toBeFalsy(); - expect(stdout).toContain(`stats: { ${propName}: false }`); + expect(stdout).toContain(`${propName}: false`); }); } } @@ -43,7 +43,7 @@ describe('stats config related flag', () => { expect(exitCode).toBe(0); expect(stderr).toBeFalsy(); - expect(stdout).toContain(`stats: { ${propName}: 10 }`); + expect(stdout).toContain(`${propName}: 10`); }); } @@ -57,13 +57,13 @@ describe('stats config related flag', () => { expect(exitCode).toBe(0); expect(stderr).toBeFalsy(); - expect(stdout).toContain(`stats: { colors: { ${option}: 'u001b[32m' } }`); + expect(stdout).toContain(`colors: { ${option}: 'u001b[32m' }`); } else if (acceptsSingleValue.includes(propName)) { const { exitCode, stderr, stdout } = run(__dirname, [`--${flag.name}`, 'log']); expect(exitCode).toBe(0); expect(stderr).toBeFalsy(); - expect(stdout).toContain(`stats: { ${propName}: 'log' }`); + expect(stdout).toContain(`${propName}: 'log'`); } else if (flag.name === 'stats-context') { const { exitCode, stderr, stdout } = run(__dirname, [`--${flag.name}`, 'log']); @@ -75,13 +75,13 @@ describe('stats config related flag', () => { expect(exitCode).toBe(0); expect(stderr).toBeFalsy(); - expect(stdout).toContain(`stats: { ${propName}: 'auto' }`); + expect(stdout).toContain(`${propName}: 'auto'`); } else { const { exitCode, stderr, stdout } = run(__dirname, [`--${flag.name}`, 'log']); expect(exitCode).toBe(0); expect(stderr).toBeFalsy(); - expect(stdout).toContain(`stats: { ${propName}: [ 'log' ] }`); + expect(stdout).toContain(`${propName}: [ 'log' ]`); } }); } diff --git a/test/serve/basic/serve-basic.test.js b/test/serve/basic/serve-basic.test.js index f9f68736d73..5a05c90fa80 100644 --- a/test/serve/basic/serve-basic.test.js +++ b/test/serve/basic/serve-basic.test.js @@ -1,5 +1,6 @@ 'use strict'; +const stripAnsi = require('strip-ansi'); const path = require('path'); const getPort = require('get-port'); const { runServe, isWebpack5, isDevServer4 } = require('../../utils/test-utils'); @@ -66,6 +67,22 @@ describe('basic serve usage', () => { expect(stdout.match(/HotModuleReplacementPlugin/g)).toBeNull(); }); + it('should work with the "--stats" option', async () => { + const { stderr, stdout } = await runServe(['--stats'], __dirname); + + expect(stderr).toBeFalsy(); + expect(stripAnsi(stdout)).toContain(isWebpack5 ? 'compiled successfully' : 'Version: webpack'); + expect(stdout.match(/HotModuleReplacementPlugin/g)).toBeNull(); + }); + + it('should work with the "--stats detailed" option', async () => { + const { stderr, stdout } = await runServe(['--stats', 'verbose'], __dirname); + + expect(stderr).toBeFalsy(); + expect(stdout).toContain(isWebpack5 ? 'from webpack.Compiler' : 'webpack.buildChunkGraph.visitModules'); + expect(stdout.match(/HotModuleReplacementPlugin/g)).toBeNull(); + }); + it('should work with the "--mode" option #2', async () => { const { stderr, stdout } = await runServe(['--mode', 'production'], __dirname); @@ -169,7 +186,7 @@ describe('basic serve usage', () => { expect(stderr).toBeFalsy(); expect(stdout).toContain('main.js'); - expect(stdout).toContain('from /'); + expect(stripAnsi(stdout)).toContain('from /'); expect(stdout.match(/HotModuleReplacementPlugin/g)).toBeNull(); }); diff --git a/test/stats/config-no/no-stats-with-config.test.js b/test/stats/config-no/no-stats-with-config.test.js index 1c4ab3da1a0..862fdfbac1d 100644 --- a/test/stats/config-no/no-stats-with-config.test.js +++ b/test/stats/config-no/no-stats-with-config.test.js @@ -1,7 +1,6 @@ 'use strict'; -const { run } = require('../../utils/test-utils'); -const { version } = require('webpack'); +const { run, isWebpack5 } = require('../../utils/test-utils'); describe('stats flag', () => { it(`should use stats 'detailed' as defined in webpack config`, () => { @@ -10,10 +9,12 @@ describe('stats flag', () => { expect(exitCode).toBe(0); expect(stderr).toBeFalsy(); - if (version.startsWith('5')) { - expect(stdout).toContain(`stats: { preset: 'detailed' }`); + if (isWebpack5) { + expect(stdout).toContain("preset: 'detailed'"); } else { - expect(stdout).toContain(`stats: 'detailed'`); + expect(stdout).toContain('entrypoints: true'); + expect(stdout).toContain('logging: true'); + expect(stdout).toContain('maxModules: Infinity'); } }); @@ -23,10 +24,10 @@ describe('stats flag', () => { expect(exitCode).toBe(0); expect(stderr).toBeFalsy(); - if (version.startsWith('5')) { - expect(stdout).toContain(`stats: { preset: 'none' }`); + if (isWebpack5) { + expect(stdout).toContain("preset: 'none'"); } else { - expect(stdout).toContain(`stats: false`); + expect(stdout).toContain('all: false'); } }); }); diff --git a/test/stats/config/index.js b/test/stats/config/index.js index cb15d2ae8df..2457f618e17 100644 --- a/test/stats/config/index.js +++ b/test/stats/config/index.js @@ -1,4 +1 @@ -require('react'); -require('react-dom'); -require('redux'); -require('react-redux'); +console.log('HERE'); diff --git a/test/stats/config/package.json b/test/stats/config/package.json deleted file mode 100644 index e04e6b3419c..00000000000 --- a/test/stats/config/package.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "dependencies": { - "react": "^16.13.0", - "react-dom": "^16.13.0", - "redux": "^4.0.5", - "react-redux": "^7.2.0" - } -} diff --git a/test/stats/config/stats.test.js b/test/stats/config/stats.test.js index 6d4510b5224..288e4a44249 100644 --- a/test/stats/config/stats.test.js +++ b/test/stats/config/stats.test.js @@ -1,8 +1,6 @@ -/* eslint-disable node/no-extraneous-require */ 'use strict'; -// eslint-disable-next-line node/no-unpublished-require + const { run, isWebpack5 } = require('../../utils/test-utils'); -const { version } = require('webpack'); // 'normal' is used in webpack.config.js const statsPresets = ['detailed', 'errors-only', 'errors-warnings', 'minimal', 'verbose', 'none']; @@ -18,10 +16,10 @@ describe('stats flag with config', () => { expect(exitCode).toBe(0); expect(stderr).toBeFalsy(); - if (version.startsWith('5')) { - expect(stdout).toContain(`stats: { preset: 'normal' }`); + if (isWebpack5) { + expect(stdout).toContain("preset: 'normal'"); } else { - expect(stdout).toContain(`stats: 'normal'`); + expect(stdout).toContain("stats: 'normal'"); } }); @@ -33,9 +31,38 @@ describe('stats flag with config', () => { expect(stderr).toBeFalsy(); if (isWebpack5) { - expect(stdout).toContain(`stats: { preset: '${preset}' }`); + expect(stdout).toContain(`preset: '${preset}'`); } else { - expect(stdout).toContain(`stats: '${preset}'`); + switch (preset) { + case 'normal': + expect(stdout).toContain('stats:'); + break; + case 'detailed': + expect(stdout).toContain('entrypoints: true'); + expect(stdout).toContain('errorDetails: true'); + break; + case 'errors-only': + expect(stdout).toContain('all: false'); + expect(stdout).toContain('errors: true'); + break; + case 'errors-warnings': + expect(stdout).toContain('all: false'); + expect(stdout).toContain('errors: true'); + expect(stdout).toContain('warnings: true'); + break; + case 'minimal': + expect(stdout).toContain('modules: true'); + expect(stdout).toContain('maxModules: 0'); + break; + case 'verbose': + expect(stdout).toContain("logging: 'verbose'"); + break; + case 'none': + expect(stdout).toContain('all: false'); + break; + default: + expect(stdout).toContain(`preset: '${preset}'`); + } } }); } diff --git a/test/stats/config/webpack.config.js b/test/stats/config/webpack.config.js index 30fb429bbc1..eb8d44f4507 100644 --- a/test/stats/config/webpack.config.js +++ b/test/stats/config/webpack.config.js @@ -1,5 +1,5 @@ -/* eslint-disable node/no-unpublished-require */ const WebpackCLITestPlugin = require('../../utils/webpack-cli-test-plugin'); + module.exports = { mode: 'development', entry: './index.js', diff --git a/test/stats/flags/index.js b/test/stats/flags/index.js index fb8848faae4..2457f618e17 100644 --- a/test/stats/flags/index.js +++ b/test/stats/flags/index.js @@ -1,4 +1 @@ -require('../config/node_modules/react'); -require('../config/node_modules/react-dom'); -require('../config/node_modules/redux'); -require('../config/node_modules/react-redux'); +console.log('HERE'); diff --git a/test/stats/flags/package.json b/test/stats/flags/package.json deleted file mode 100644 index e04e6b3419c..00000000000 --- a/test/stats/flags/package.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "dependencies": { - "react": "^16.13.0", - "react-dom": "^16.13.0", - "redux": "^4.0.5", - "react-redux": "^7.2.0" - } -} diff --git a/test/stats/flags/stats.test.js b/test/stats/flags/stats.test.js index 0f37921c315..407c237f9f7 100644 --- a/test/stats/flags/stats.test.js +++ b/test/stats/flags/stats.test.js @@ -1,4 +1,3 @@ -/* eslint-disable node/no-unpublished-require */ 'use strict'; const { run, isWebpack5 } = require('../../utils/test-utils'); @@ -18,9 +17,38 @@ describe('stats flag', () => { expect(stderr).toBeFalsy(); if (isWebpack5) { - expect(stdout).toContain(`stats: { preset: '${preset}' }`); + expect(stdout).toContain(`preset: '${preset}'`); } else { - expect(stdout).toContain(`stats: '${preset}'`); + switch (preset) { + case 'normal': + expect(stdout).toContain('stats:'); + break; + case 'detailed': + expect(stdout).toContain('entrypoints: true'); + expect(stdout).toContain('errorDetails: true'); + break; + case 'errors-only': + expect(stdout).toContain('all: false'); + expect(stdout).toContain('errors: true'); + break; + case 'errors-warnings': + expect(stdout).toContain('all: false'); + expect(stdout).toContain('errors: true'); + expect(stdout).toContain('warnings: true'); + break; + case 'minimal': + expect(stdout).toContain('modules: true'); + expect(stdout).toContain('maxModules: 0'); + break; + case 'verbose': + expect(stdout).toContain("logging: 'verbose'"); + break; + case 'none': + expect(stdout).toContain('all: false'); + break; + default: + expect(stdout).toContain(`preset: '${preset}'`); + } } }); } @@ -32,9 +60,9 @@ describe('stats flag', () => { expect(stderr).toBeFalsy(); if (isWebpack5) { - expect(stdout).toContain(`stats: { preset: 'normal' }`); + expect(stdout).toContain("preset: 'normal'"); } else { - expect(stdout).toContain('stats: true'); + expect(stdout).toContain('stats:'); } }); @@ -45,9 +73,9 @@ describe('stats flag', () => { expect(stderr).toBeFalsy(); if (isWebpack5) { - expect(stdout).toContain(`stats: { preset: 'none' }`); + expect(stdout).toContain("preset: 'none'"); } else { - expect(stdout).toContain('stats: false'); + expect(stdout).toContain('all: false'); } }); diff --git a/yarn.lock b/yarn.lock index 3c3af9ca1da..255c7875a6c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8194,18 +8194,25 @@ mime-db@1.44.0: resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.44.0.tgz#fa11c5eb0aca1334b4233cb4d52f10c5a6272f92" integrity sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg== -"mime-db@>= 1.43.0 < 2": +mime-db@1.45.0, "mime-db@>= 1.43.0 < 2": version "1.45.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.45.0.tgz#cceeda21ccd7c3a745eba2decd55d4b73e7879ea" integrity sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w== -mime-types@^2.1.12, mime-types@^2.1.27, mime-types@~2.1.17, mime-types@~2.1.19, mime-types@~2.1.24: +mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.19, mime-types@~2.1.24: version "2.1.27" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.27.tgz#47949f98e279ea53119f5722e0f34e529bec009f" integrity sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w== dependencies: mime-db "1.44.0" +mime-types@^2.1.27: + version "2.1.28" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.28.tgz#1160c4757eab2c5363888e005273ecf79d2a0ecd" + integrity sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ== + dependencies: + mime-db "1.45.0" + mime@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" @@ -11664,7 +11671,7 @@ webpack-sources@^2.1.1: source-list-map "^2.0.1" source-map "^0.6.1" -webpack@^5.11.0: +webpack@^5.11.1: version "5.11.1" resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.11.1.tgz#39b2b9daeb5c6c620e03b7556ec674eaed4016b4" integrity sha512-tNUIdAmYJv+nupRs/U/gqmADm6fgrf5xE+rSlSsf2PgsGO7j2WG7ccU6AWNlOJlHFl+HnmXlBmHIkiLf+XA9mQ==