diff --git a/packages/serve/__tests__/__snapshots__/parseArgs.test.ts.snap b/packages/serve/__tests__/__snapshots__/parseArgs.test.ts.snap index ed8b7e3084c..1a5efa72526 100644 --- a/packages/serve/__tests__/__snapshots__/parseArgs.test.ts.snap +++ b/packages/serve/__tests__/__snapshots__/parseArgs.test.ts.snap @@ -10,7 +10,6 @@ Object { "serveIndex": true, }, "webpackArgs": Object { - "color": true, "env": Object { "WEBPACK_SERVE": true, }, @@ -41,7 +40,6 @@ Object { "serveIndex": true, }, "webpackArgs": Object { - "color": true, "env": Object { "WEBPACK_SERVE": true, }, diff --git a/packages/webpack-cli/lib/bootstrap.js b/packages/webpack-cli/lib/bootstrap.js index b6fc82879c6..6ff74f315cf 100644 --- a/packages/webpack-cli/lib/bootstrap.js +++ b/packages/webpack-cli/lib/bootstrap.js @@ -4,6 +4,7 @@ const logger = require('./utils/logger'); const { isCommandUsed } = require('./utils/arg-utils'); const argParser = require('./utils/arg-parser'); const leven = require('leven'); +const { options: coloretteOptions } = require('colorette'); process.title = 'webpack-cli'; @@ -23,6 +24,11 @@ const runCLI = async (cliArgs) => { // If the unknown arg starts with a '-', it will be considered an unknown flag rather than an entry let entry; + // enable/disable colors + if (typeof parsedArgs.opts.color !== 'undefined') { + coloretteOptions.enabled = Boolean(parsedArgs.opts.color); + } + if (parsedArgs.unknownArgs.length > 0) { entry = []; diff --git a/packages/webpack-cli/lib/utils/cli-flags.js b/packages/webpack-cli/lib/utils/cli-flags.js index 195330f92e3..6840cbf0f1f 100644 --- a/packages/webpack-cli/lib/utils/cli-flags.js +++ b/packages/webpack-cli/lib/utils/cli-flags.js @@ -92,7 +92,6 @@ const core = [ usage: '--color', type: Boolean, negative: true, - defaultValue: true, description: 'Enable/Disable colors on console', }, { diff --git a/packages/webpack-cli/lib/webpack-cli.js b/packages/webpack-cli/lib/webpack-cli.js index d661a7cb865..950adaef7e9 100644 --- a/packages/webpack-cli/lib/webpack-cli.js +++ b/packages/webpack-cli/lib/webpack-cli.js @@ -47,9 +47,8 @@ class WebpackCLI { } async resolveArgs(args, configOptions = {}) { - // Since color flag has a default value, when there are no other args then exit // eslint-disable-next-line no-prototype-builtins - if (Object.keys(args).length === 1 && args.hasOwnProperty('color') && !process.env.NODE_ENV) return {}; + if (Object.keys(args).length === 0 && !process.env.NODE_ENV) return {}; const { outputPath, stats, json, mode, target, prefetch, hot, analyze } = args; const finalOptions = { @@ -327,6 +326,10 @@ class WebpackCLI { let options = this.compilerConfiguration; let outputOptions = this.outputConfiguration; + if (typeof args.color !== 'undefined') { + coloretteOptions.enabled = Boolean(args.color); + } + const isRawOutput = typeof outputOptions.json === 'undefined'; if (isRawOutput) { @@ -399,12 +402,6 @@ class WebpackCLI { compiler = this.createCompiler(options, callback); - if (compiler && outputOptions.interactive) { - const interactive = require('./utils/interactive'); - - interactive(compiler, options, outputOptions); - } - return Promise.resolve(); } } diff --git a/test/colors/colors.test.js b/test/colors/colors.test.js index 4bc9e30fbfb..2e6536eb10c 100644 --- a/test/colors/colors.test.js +++ b/test/colors/colors.test.js @@ -43,6 +43,25 @@ describe('colorts', () => { expect(exitCode).toBe(0); }); + it('should disable colored output with --no-color', () => { + const { stderr, stdout, exitCode } = run(__dirname, ['--stats=verbose', '--no-color']); + + expect(stderr).toBeFalsy(); + const output = isWebpack5 ? 'successfully' : 'main.js'; + expect(stdout).not.toContain(`\u001b[1m\u001b[32m${output}\u001b[39m\u001b[22m`); + expect(stdout).toContain(output); + expect(exitCode).toBe(0); + }); + + it('should work with the "stats" option and --color flags', () => { + const { stderr, stdout, exitCode } = run(__dirname, ['--stats=verbose', '--color']); + + expect(stderr).toBeFalsy(); + const output = isWebpack5 ? 'successfully' : 'main.js'; + expect(stdout).toContain(`\u001b[1m\u001b[32m${output}\u001b[39m\u001b[22m`); + expect(exitCode).toBe(0); + }); + it('should work with the "stats" option from the configuration', () => { const { stderr, stdout, exitCode } = run(__dirname, ['--config=stats-string.webpack.config.js']); diff --git a/test/config/type/function-with-argv/function-with-argv.test.js b/test/config/type/function-with-argv/function-with-argv.test.js index 26d7cb94240..efbb0e2b33c 100644 --- a/test/config/type/function-with-argv/function-with-argv.test.js +++ b/test/config/type/function-with-argv/function-with-argv.test.js @@ -9,7 +9,7 @@ describe('function configuration', () => { expect(stderr).toBeFalsy(); expect(stdout).toBeTruthy(); expect(exitCode).toBe(0); - expect(stdout).toContain("argv: { color: true, mode: 'development' }"); + expect(stdout).toContain("argv: { mode: 'development' }"); // Should generate the appropriate files expect(existsSync(resolve(__dirname, './dist/dev.js'))).toBeTruthy(); }); diff --git a/test/json/json.test.js b/test/json/json.test.js index a248412bc0d..c395d484ebc 100644 --- a/test/json/json.test.js +++ b/test/json/json.test.js @@ -3,6 +3,8 @@ const { run } = require('../utils/test-utils'); const { stat, readFile } = require('fs'); const { resolve } = require('path'); +const successMessage = 'stats are successfully stored as json to stats.json'; + describe('json flag', () => { it('should return valid json', () => { const { stdout, exitCode } = run(__dirname, ['--json']); @@ -16,7 +18,50 @@ describe('json flag', () => { it('should store json to a file', (done) => { const { stdout, exitCode } = run(__dirname, ['--json', 'stats.json']); - expect(stdout).toContain('stats are successfully stored as json to stats.json'); + expect(stdout).toContain(successMessage); + expect(exitCode).toBe(0); + + stat(resolve(__dirname, './stats.json'), (err, stats) => { + expect(err).toBe(null); + expect(stats.isFile()).toBe(true); + + readFile(resolve(__dirname, 'stats.json'), 'utf-8', (err, data) => { + expect(err).toBe(null); + expect(JSON.parse(data)['hash']).toBeTruthy(); + expect(JSON.parse(data)['version']).toBeTruthy(); + expect(JSON.parse(data)['time']).toBeTruthy(); + expect(() => JSON.parse(data)).not.toThrow(); + done(); + }); + }); + }); + + it('should store json to a file and respect --color flag', (done) => { + const { stdout, exitCode } = run(__dirname, ['--json', 'stats.json', '--color']); + + expect(stdout).toContain(`[webpack-cli] \u001b[32m${successMessage}`); + expect(exitCode).toBe(0); + + stat(resolve(__dirname, './stats.json'), (err, stats) => { + expect(err).toBe(null); + expect(stats.isFile()).toBe(true); + + readFile(resolve(__dirname, 'stats.json'), 'utf-8', (err, data) => { + expect(err).toBe(null); + expect(JSON.parse(data)['hash']).toBeTruthy(); + expect(JSON.parse(data)['version']).toBeTruthy(); + expect(JSON.parse(data)['time']).toBeTruthy(); + expect(() => JSON.parse(data)).not.toThrow(); + done(); + }); + }); + }); + + it('should store json to a file and respect --no-color', (done) => { + const { stdout, exitCode } = run(__dirname, ['--json', 'stats.json', '--no-color']); + + expect(stdout).not.toContain(`[webpack-cli] \u001b[32m${successMessage}`); + expect(stdout).toContain(`[webpack-cli] ${successMessage}`); expect(exitCode).toBe(0); stat(resolve(__dirname, './stats.json'), (err, stats) => { diff --git a/test/unknown/unknown.test.js b/test/unknown/unknown.test.js index 903122b2495..78518a58af3 100644 --- a/test/unknown/unknown.test.js +++ b/test/unknown/unknown.test.js @@ -1,12 +1,30 @@ const { run } = require('../utils/test-utils'); +const unknownError = 'Unknown argument: --unknown'; + describe('unknown behaviour', () => { - it('warns the user if an unknown flag is passed in', () => { + it('throws error if an unknown flag is passed in', () => { const { stderr, exitCode } = run(__dirname, ['--unknown']); expect(stderr).toBeTruthy(); - expect(stderr).toContain('Unknown argument: --unknown'); + expect(stderr).toContain(unknownError); + expect(exitCode).toBe(2); + }); + + it('should throw error and respect --color flag', () => { + const { stderr, exitCode } = run(__dirname, ['--unknown', '--color']); + expect(stderr).toBeTruthy(); + expect(stderr).toContain(`[webpack-cli] \u001b[31m${unknownError}`); expect(exitCode).toBe(2); }); + + it('throws error for unknow flag and respect --no-color', () => { + const { stderr, exitCode } = run(__dirname, ['--unknown', '--no-color']); + expect(stderr).toBeTruthy(); + expect(stderr).not.toContain(`[webpack-cli] \u001b[31m${unknownError}`); + expect(stderr).toContain(unknownError); + expect(exitCode).toBe(2); + }); + it('suggests the closest match to an unknown flag', () => { const { stderr, stdout, exitCode } = run(__dirname, ['--entyr', './a.js']); expect(stderr).toContain('Unknown argument: --entyr');