diff --git a/packages/webpack-cli/lib/utils/Compiler.js b/packages/webpack-cli/lib/utils/Compiler.js index 15279dc855b..61f491d5a1a 100644 --- a/packages/webpack-cli/lib/utils/Compiler.js +++ b/packages/webpack-cli/lib/utils/Compiler.js @@ -129,10 +129,17 @@ class Compiler { this.compiler = await webpack(options); this.compilerOptions = options; } catch (err) { - process.stdout.write('\n'); - logger.error(`${err.name}: ${err.message}`); - process.stdout.write('\n'); - return; + // https://github.com/webpack/webpack/blob/master/lib/index.js#L267 + // https://github.com/webpack/webpack/blob/v4.44.2/lib/webpack.js#L90 + const ValidationError = webpack.ValidationError ? webpack.ValidationError : webpack.WebpackOptionsValidationError; + // In case of schema errors print and exit process + // For webpack@4 and webpack@5 + if (err instanceof ValidationError) { + logger.error(`\n${err.message}`); + } else { + logger.error(`\n${err}`); + } + process.exit(1); } } @@ -153,7 +160,6 @@ class Compiler { const interactive = require('./interactive'); return interactive(options, outputOptions); } - if (this.compiler.compilers) { this.compiler.compilers.forEach((comp, idx) => { bailAndWatchWarning(comp); //warn the user if bail and watch both are used together diff --git a/test/core-flags/devtool-flag.test.js b/test/core-flags/devtool-flag.test.js index 60aa498ad20..fec3a3a30a3 100644 --- a/test/core-flags/devtool-flag.test.js +++ b/test/core-flags/devtool-flag.test.js @@ -13,6 +13,6 @@ describe('--devtool flag', () => { it('should throw error for invalid config', () => { const { stderr } = run(__dirname, ['--devtool', 'invalid']); - expect(stderr).toContain('ValidationError: Invalid configuration object'); + expect(stderr).toContain('Invalid configuration object'); }); }); diff --git a/test/invalid-schema/invalid-schema.test.js b/test/invalid-schema/invalid-schema.test.js new file mode 100644 index 00000000000..090fdefede9 --- /dev/null +++ b/test/invalid-schema/invalid-schema.test.js @@ -0,0 +1,23 @@ +'use strict'; +const { run, isWindows } = require('../utils/test-utils'); + +describe('invalid schema', () => { + it('should log webpack error and exit process on invalid config', () => { + const { stderr, stdout, exitCode } = run(__dirname, ['--config', './webpack.config.mock.js']); + console.log({ stderr, stdout, exitCode }); + expect(stderr).toContain('Invalid configuration object'); + // TODO - Fix exitcode check on windows + if (!isWindows) { + expect(exitCode).toEqual(1); + } + }); + + it('should log webpack error and exit process on invalid flag', () => { + const { stderr, exitCode } = run(__dirname, ['--mode', 'Yukihira']); + expect(stderr).toContain('Invalid configuration object'); + // TODO - Fix exitcode check on windows + if (!isWindows) { + expect(exitCode).toEqual(1); + } + }); +}); diff --git a/test/invalid-schema/webpack.config.mock.js b/test/invalid-schema/webpack.config.mock.js new file mode 100644 index 00000000000..f6d8ff0ce80 --- /dev/null +++ b/test/invalid-schema/webpack.config.mock.js @@ -0,0 +1,3 @@ +module.exports = { + mode: 'Nishinoya Yuu', +}; diff --git a/test/stats/cli-flags/stats.test.js b/test/stats/cli-flags/stats.test.js index c859f89d8da..963c637deb9 100644 --- a/test/stats/cli-flags/stats.test.js +++ b/test/stats/cli-flags/stats.test.js @@ -1,7 +1,7 @@ /* eslint-disable node/no-extraneous-require */ /* eslint-disable node/no-unpublished-require */ 'use strict'; -const { run, isWebpack5 } = require('../../utils/test-utils'); +const { run, isWebpack5, isWindows } = require('../../utils/test-utils'); const presets = ['normal', 'detailed', 'errors-only', 'errors-warnings', 'minimal', 'verbose', 'none']; @@ -33,7 +33,7 @@ describe('stats flag', () => { }); it('should warn when an unknown flag stats value is passed', () => { - const { stderr, stdout } = run(__dirname, ['--stats', 'foo']); + const { stderr, exitCode } = run(__dirname, ['--stats', 'foo']); expect(stderr).toBeTruthy(); expect(stderr).toContain('* configuration.stats should be one of these:'); if (isWebpack5) { @@ -43,6 +43,9 @@ describe('stats flag', () => { } else { expect(stderr).toContain('"none" | "errors-only" | "minimal" | "normal" | "detailed" | "verbose" | "errors-warnings"'); } - expect(stdout).toBeTruthy(); + // TODO - Fix exitcode check on windows + if (!isWindows) { + expect(exitCode).toEqual(1); + } }); }); diff --git a/test/target/flag-test/target-flag.test.js b/test/target/flag-test/target-flag.test.js index 2e85a918786..0d15d20293a 100644 --- a/test/target/flag-test/target-flag.test.js +++ b/test/target/flag-test/target-flag.test.js @@ -43,7 +43,7 @@ describe('--target flag', () => { it(`should throw error with invalid value for --target`, () => { const { stderr } = run(__dirname, ['--target', 'invalid']); if (isWebpack5) { - expect(stderr).toContain(`Error: Unknown target 'invalid'`); + expect(stderr).toContain(`Unknown target 'invalid'`); } else { expect(stderr).toContain('Invalid configuration object'); }