Skip to content

Commit

Permalink
fix: error message on invalid plugin options (#2380)
Browse files Browse the repository at this point in the history
  • Loading branch information
alexander-akait committed Jan 28, 2021
1 parent 311bae3 commit f9ce1d3
Show file tree
Hide file tree
Showing 7 changed files with 139 additions and 35 deletions.
2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -91,7 +91,7 @@
"strip-ansi": "^6.0.0",
"ts-jest": "^26.4.3",
"typescript": "^4.1.3",
"webpack": "^5.17.0",
"webpack": "^5.18.0",
"webpack-bundle-analyzer": "^4.3.0",
"webpack-dev-server": "^3.11.1",
"yeoman-test": "^2.7.0"
Expand Down
2 changes: 1 addition & 1 deletion packages/serve/src/index.ts
Expand Up @@ -113,7 +113,7 @@ class ServeCommand {
try {
servers = await startDevServer(compiler, devServerOptions, options, logger);
} catch (error) {
if (error.name === 'ValidationError') {
if (cli.isValidationError(error)) {
logger.error(error.message);
} else {
logger.error(error);
Expand Down
26 changes: 16 additions & 10 deletions packages/webpack-cli/lib/webpack-cli.js
Expand Up @@ -1172,7 +1172,13 @@ class WebpackCLI {
}
} catch (error) {
logger.error(`Failed to load '${configPath}' config`);
logger.error(error);

if (this.isValidationError(error)) {
logger.error(error.message);
} else {
logger.error(error);
}

process.exit(2);
}

Expand Down Expand Up @@ -1602,15 +1608,15 @@ class WebpackCLI {
return compiler.options.watchOptions && compiler.options.watchOptions.stdin;
}

async createCompiler(options, callback) {
const isValidationError = (error) => {
// 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 = this.webpack.ValidationError || this.webpack.WebpackOptionsValidationError;
isValidationError(error) {
// 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 = this.webpack.ValidationError || this.webpack.WebpackOptionsValidationError;

return error instanceof ValidationError;
};
return error instanceof ValidationError || error.name === 'ValidationError';
}

async createCompiler(options, callback) {
let config = await this.resolveConfig(options);

config = await this.applyOptions(config, options);
Expand All @@ -1623,7 +1629,7 @@ class WebpackCLI {
config.options,
callback
? (error, stats) => {
if (isValidationError(error)) {
if (error && this.isValidationError(error)) {
logger.error(error.message);
process.exit(2);
}
Expand All @@ -1633,7 +1639,7 @@ class WebpackCLI {
: callback,
);
} catch (error) {
if (isValidationError(error)) {
if (this.isValidationError(error)) {
logger.error(error.message);
} else {
logger.error(error);
Expand Down
89 changes: 86 additions & 3 deletions test/error/invalid-schema/invalid-schema.test.js
Expand Up @@ -3,23 +3,31 @@ const { run, isWebpack5 } = require('../../utils/test-utils');

describe('invalid schema', () => {
it('should log error on invalid config', () => {
const { exitCode, stderr, stdout } = run(__dirname, ['--config', './webpack.config.mock.js']);
const { exitCode, stderr, stdout } = run(__dirname, ['--config', './webpack.mock.config.js']);

expect(exitCode).toEqual(2);
expect(stderr).toContain('Invalid configuration object');
expect(stdout).toBeFalsy();
});

it('should log error on invalid plugin options', () => {
const { exitCode, stderr, stdout } = run(__dirname, ['--config', './webpack.plugin-mock.config.js']);

expect(exitCode).toEqual(2);
expect(stderr).toContain(isWebpack5 ? 'Invalid options object' : 'Invalid Options');
expect(stdout).toBeFalsy();
});

it('should log error on invalid config using the "bundle" command', () => {
const { exitCode, stderr, stdout } = run(__dirname, ['bundle', '--config', './webpack.config.mock.js']);
const { exitCode, stderr, stdout } = run(__dirname, ['bundle', '--config', './webpack.mock.config.js']);

expect(exitCode).toEqual(2);
expect(stderr).toContain('Invalid configuration object');
expect(stdout).toBeFalsy();
});

it('should log error on invalid config using the "serve" command', () => {
const { exitCode, stderr, stdout } = run(__dirname, ['serve', '--config', './webpack.config.mock.js']);
const { exitCode, stderr, stdout } = run(__dirname, ['serve', '--config', './webpack.mock.config.js']);

expect(exitCode).toEqual(2);
expect(stderr).toContain('Invalid configuration object');
Expand All @@ -41,6 +49,21 @@ describe('invalid schema', () => {
expect(stdout).toBeFalsy();
});

it('should log error on invalid option using "build" command', () => {
const { exitCode, stderr, stdout } = run(__dirname, ['build', '--mode', 'Yukihira']);

expect(exitCode).toEqual(2);

if (isWebpack5) {
expect(stderr).toContain("Invalid value 'Yukihira' for the '--mode' option");
expect(stderr).toContain("Expected: 'development | production | none'");
} else {
expect(stderr).toContain('Invalid configuration object');
}

expect(stdout).toBeFalsy();
});

it('should log error on invalid option using "bundle" command', () => {
const { exitCode, stderr, stdout } = run(__dirname, ['bundle', '--mode', 'Yukihira']);

Expand All @@ -56,6 +79,51 @@ describe('invalid schema', () => {
expect(stdout).toBeFalsy();
});

it('should log error on invalid option using "b" command', () => {
const { exitCode, stderr, stdout } = run(__dirname, ['b', '--mode', 'Yukihira']);

expect(exitCode).toEqual(2);

if (isWebpack5) {
expect(stderr).toContain("Invalid value 'Yukihira' for the '--mode' option");
expect(stderr).toContain("Expected: 'development | production | none'");
} else {
expect(stderr).toContain('Invalid configuration object');
}

expect(stdout).toBeFalsy();
});

it('should log error on invalid option using "watch" command', () => {
const { exitCode, stderr, stdout } = run(__dirname, ['watch', '--mode', 'Yukihira']);

expect(exitCode).toEqual(2);

if (isWebpack5) {
expect(stderr).toContain("Invalid value 'Yukihira' for the '--mode' option");
expect(stderr).toContain("Expected: 'development | production | none'");
} else {
expect(stderr).toContain('Invalid configuration object');
}

expect(stdout).toBeFalsy();
});

it('should log error on invalid option using "w" command', () => {
const { exitCode, stderr, stdout } = run(__dirname, ['w', '--mode', 'Yukihira']);

expect(exitCode).toEqual(2);

if (isWebpack5) {
expect(stderr).toContain("Invalid value 'Yukihira' for the '--mode' option");
expect(stderr).toContain("Expected: 'development | production | none'");
} else {
expect(stderr).toContain('Invalid configuration object');
}

expect(stdout).toBeFalsy();
});

it('should log error on invalid option using "server" command', () => {
const { exitCode, stderr, stdout } = run(__dirname, ['serve', '--mode', 'Yukihira']);

Expand All @@ -70,4 +138,19 @@ describe('invalid schema', () => {

expect(stdout).toBeFalsy();
});

it('should log error on invalid option using "s" command', () => {
const { exitCode, stderr, stdout } = run(__dirname, ['s', '--mode', 'Yukihira']);

expect(exitCode).toEqual(2);

if (isWebpack5) {
expect(stderr).toContain("Invalid value 'Yukihira' for the '--mode' option");
expect(stderr).toContain("Expected: 'development | production | none'");
} else {
expect(stderr).toContain('Invalid configuration object');
}

expect(stdout).toBeFalsy();
});
});
10 changes: 10 additions & 0 deletions test/error/invalid-schema/webpack.plugin-mock.config.js
@@ -0,0 +1,10 @@
const webpack = require('webpack');

module.exports = {
mode: 'development',
plugins: [
new webpack.BannerPlugin({
unknown: 'unknown',
}),
],
};
45 changes: 25 additions & 20 deletions yarn.lock
Expand Up @@ -1895,11 +1895,16 @@
jest-diff "^26.0.0"
pretty-format "^26.0.0"

"@types/json-schema@*", "@types/json-schema@^7.0.3", "@types/json-schema@^7.0.6":
"@types/json-schema@*", "@types/json-schema@^7.0.3":
version "7.0.6"
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.6.tgz#f4c7ec43e81b319a9815115031709f26987891f0"
integrity sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw==

"@types/json-schema@^7.0.6":
version "7.0.7"
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.7.tgz#98a993516c859eb0d5c4c8f098317a9ea68db9ad"
integrity sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA==

"@types/keyv@*":
version "3.1.1"
resolved "https://registry.yarnpkg.com/@types/keyv/-/keyv-3.1.1.tgz#e45a45324fca9dab716ab1230ee249c9fb52cfa7"
Expand Down Expand Up @@ -2863,15 +2868,15 @@ browser-process-hrtime@^1.0.0:
integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==

browserslist@^4.14.5:
version "4.15.0"
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.15.0.tgz#3d48bbca6a3f378e86102ffd017d9a03f122bdb0"
integrity sha512-IJ1iysdMkGmjjYeRlDU8PQejVwxvVO5QOfXH7ylW31GO6LwNRSmm/SgRXtNsEXqMLl2e+2H5eEJ7sfynF8TCaQ==
version "4.16.1"
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.16.1.tgz#bf757a2da376b3447b800a16f0f1c96358138766"
integrity sha512-UXhDrwqsNcpTYJBTZsbGATDxZbiVDsx6UjpmRUmtnP10pr8wAYr5LgFoEFw9ixriQH2mv/NX2SfGzE/o8GndLA==
dependencies:
caniuse-lite "^1.0.30001164"
caniuse-lite "^1.0.30001173"
colorette "^1.2.1"
electron-to-chromium "^1.3.612"
electron-to-chromium "^1.3.634"
escalade "^3.1.1"
node-releases "^1.1.67"
node-releases "^1.1.69"

bs-logger@0.x:
version "0.2.6"
Expand Down Expand Up @@ -3066,10 +3071,10 @@ camelcase@^6.0.0:
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.2.0.tgz#924af881c9d525ac9d87f40d964e5cea982a1809"
integrity sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==

caniuse-lite@^1.0.30001164:
version "1.0.30001165"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001165.tgz#32955490d2f60290bb186bb754f2981917fa744f"
integrity sha512-8cEsSMwXfx7lWSUMA2s08z9dIgsnR5NAqjXP23stdsU3AUWkCr/rr4s4OFtHXn5XXr6+7kam3QFVoYyXNPdJPA==
caniuse-lite@^1.0.30001173:
version "1.0.30001180"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001180.tgz#67abcd6d1edf48fa5e7d1e84091d1d65ab76e33b"
integrity sha512-n8JVqXuZMVSPKiPiypjFtDTXc4jWIdjxull0f92WLo7e1MSi3uJ3NvveakSh/aCl1QKFAvIz3vIj0v+0K+FrXw==

capture-exit@^2.0.0:
version "2.0.0"
Expand Down Expand Up @@ -4147,10 +4152,10 @@ ejs@^3.0.1:
dependencies:
jake "^10.6.1"

electron-to-chromium@^1.3.612:
version "1.3.621"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.621.tgz#0bbe2100ef0b28f88d0b1101fbdf433312f69be0"
integrity sha512-FeIuBzArONbAmKmZIsZIFGu/Gc9AVGlVeVbhCq+G2YIl6QkT0TDn2HKN/FMf1btXEB9kEmIuQf3/lBTVAbmFOg==
electron-to-chromium@^1.3.634:
version "1.3.647"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.647.tgz#8f1750ab7a5137f1a9a27f8f4ebdf550e08ae10b"
integrity sha512-Or2Nu8TjkmSywY9hk85K/Y6il28hchlonITz30fkC87qvSNupQl29O12BzDDDTnUFlo6kEIFL2QGSpkZDMxH8g==

elegant-spinner@^1.0.1:
version "1.0.1"
Expand Down Expand Up @@ -8019,10 +8024,10 @@ node-preload@^0.2.1:
dependencies:
process-on-spawn "^1.0.0"

node-releases@^1.1.67:
version "1.1.67"
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.67.tgz#28ebfcccd0baa6aad8e8d4d8fe4cbc49ae239c12"
integrity sha512-V5QF9noGFl3EymEwUYzO+3NTDpGfQB4ve6Qfnzf3UNydMhjQRVPR1DZTuvWiLzaFJYw2fmDwAfnRNEVb64hSIg==
node-releases@^1.1.69:
version "1.1.70"
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.70.tgz#66e0ed0273aa65666d7fe78febe7634875426a08"
integrity sha512-Slf2s69+2/uAD79pVVQo8uSiC34+g8GWY8UH2Qtqv34ZfhYrxpYpfzs9Js9d6O0mbDmALuxaTlplnBTnSELcrw==

nopt@^4.0.1:
version "4.0.3"
Expand Down Expand Up @@ -11072,7 +11077,7 @@ webpack-sources@^2.1.1:
source-list-map "^2.0.1"
source-map "^0.6.1"

webpack@^5.17.0:
webpack@^5.18.0:
version "5.18.0"
resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.18.0.tgz#bbcf13094aa0da0534d513f27d7ee72d74e499c6"
integrity sha512-RmiP/iy6ROvVe/S+u0TrvL/oOmvP+2+Bs8MWjvBwwY/j82Q51XJyDJ75m0QAGntL1Wx6B//Xc0+4VPP/hlNHmw==
Expand Down

0 comments on commit f9ce1d3

Please sign in to comment.