From 2ef879f20d877793a3a9daf896b059349cb6c562 Mon Sep 17 00:00:00 2001 From: Ika Date: Fri, 13 Oct 2017 20:17:01 -0500 Subject: [PATCH] feat(cli): add `--loglevel` option (#2992) * feat(cli): add `--loglevel` option * fix: handle error from invalid option * fix: choice value and shouldLog logic * test: fix test cases * fix: change log style * test: truncate snapshots * test: reduce duplicate code * test: use patterns instead of snapshots * test: fix regex --- src/cli-constant.js | 14 +-- src/cli-logger.js | 48 +++++++++ src/cli-util.js | 99 ++++++++++------- src/cli-validator.js | 5 +- src/cli.js | 13 ++- .../__snapshots__/arg-parsing.js.snap | 10 +- .../__snapshots__/config-invalid.js.snap | 23 ++-- .../__snapshots__/debug-check.js.snap | 100 +++++++++--------- .../__snapshots__/early-exit.js.snap | 36 +++++-- .../__snapshots__/invalid-ignore.js.snap | 2 +- .../__snapshots__/multiple-patterns.js.snap | 2 +- .../__snapshots__/stdin-filepath.js.snap | 6 +- .../__snapshots__/syntax-error.js.snap | 6 +- .../with-config-precedence.js.snap | 15 +-- .../__tests__/__snapshots__/write.js.snap | 6 +- tests_integration/__tests__/loglevel.js | 40 +++++++ tests_integration/cli/loglevel/.prettierrc | 3 + tests_integration/runPrettier.js | 5 +- 18 files changed, 293 insertions(+), 140 deletions(-) create mode 100644 src/cli-logger.js create mode 100644 tests_integration/__tests__/loglevel.js create mode 100644 tests_integration/cli/loglevel/.prettierrc diff --git a/src/cli-constant.js b/src/cli-constant.js index f12c8b23..2d45d7a4 100644 --- a/src/cli-constant.js +++ b/src/cli-constant.js @@ -187,6 +187,12 @@ const detailedOptions = normalizeDetailedOptions({ description: "Print the names of files that are different from Prettier's formatting." }, + loglevel: { + type: "choice", + description: "What level of logs to report.", + default: "warn", + choices: ["silent", "error", "warn", "debug"] + }, parser: { type: "choice", category: CATEGORY_FORMAT, @@ -334,13 +340,7 @@ const minimistOptions = { (current, option) => Object.assign({ [option.name]: option.alias }, current), {} - ), - unknown: param => { - if (param.startsWith("-")) { - console.warn(`Ignored unknown option: ${param}\n`); - return false; - } - } + ) }; const usageSummary = ` diff --git a/src/cli-logger.js b/src/cli-logger.js new file mode 100644 index 00000000..5a390d23 --- /dev/null +++ b/src/cli-logger.js @@ -0,0 +1,48 @@ +"use strict"; + +const ENV_LOG_LEVEL = "PRETTIER_LOG_LEVEL"; + +const chalk = require("chalk"); + +const warn = createLogger("warn", "yellow"); +const error = createLogger("error", "red"); +const debug = createLogger("debug", "blue"); + +function createLogger(loggerName, color) { + const prefix = `[${chalk[color](loggerName)}] `; + return function(message) { + if (shouldLog(loggerName)) { + console.error(message.replace(/^/gm, prefix).replace(/[\t ]+$/gm, "")); + } + }; +} + +function shouldLog(loggerName) { + const logLevel = process.env[ENV_LOG_LEVEL]; + + switch (logLevel) { + case "silent": + return false; + default: + return true; + case "debug": + if (loggerName === "debug") { + return true; + } + // fall through + case "warn": + if (loggerName === "warn") { + return true; + } + // fall through + case "error": + return loggerName === "error"; + } +} + +module.exports = { + warn, + error, + debug, + ENV_LOG_LEVEL +}; diff --git a/src/cli-util.js b/src/cli-util.js index ad4f6535..80c6799a 100644 --- a/src/cli-util.js +++ b/src/cli-util.js @@ -18,6 +18,7 @@ const constant = require("./cli-constant"); const validator = require("./cli-validator"); const apiDefaultOptions = require("./options").defaults; const errors = require("./errors"); +const logger = require("./cli-logger"); const OPTION_USAGE_THRESHOLD = 25; const CHOICE_USAGE_MARGIN = 3; @@ -57,15 +58,15 @@ function handleError(filename, error) { // `util.inspect` of throws things that aren't `Error` objects. (The Flow // parser has mistakenly thrown arrays sometimes.) if (isParseError) { - console.error(`${filename}: ${String(error)}`); + logger.error(`${filename}: ${String(error)}`); } else if (isValidationError || error instanceof errors.ConfigError) { - console.error(String(error)); + logger.error(String(error)); // If validation fails for one file, it will fail for all of them. process.exit(1); } else if (error instanceof errors.DebugError) { - console.error(`${filename}: ${error.message}`); + logger.error(`${filename}: ${error.message}`); } else { - console.error(filename + ":", error.stack || error); + logger.error(filename + ": " + (error.stack || error)); } // Don't exit the process if one file failed @@ -146,25 +147,44 @@ function format(argv, input, opt) { function getOptionsOrDie(argv, filePath) { try { - return argv["config"] === false - ? null - : resolver.resolveConfig.sync(filePath, { config: argv["config"] }); + if (argv["config"] === false) { + logger.debug("'--no-config' option found, skip loading config file."); + return null; + } + + logger.debug( + argv["config"] + ? `load config file from '${argv["config"]}'` + : `resolve config from '${filePath}'` + ); + const options = resolver.resolveConfig.sync(filePath, { + config: argv["config"] + }); + + logger.debug("loaded options `" + JSON.stringify(options) + "`"); + return options; } catch (error) { - console.error("Error: Invalid configuration file."); - console.error(error.message); + logger.error("Invalid configuration file: " + error.message); process.exit(2); } } function getOptionsForFile(argv, filepath) { const options = getOptionsOrDie(argv, filepath); - return Object.assign( + + const appliedOptions = Object.assign( { filepath }, applyConfigPrecedence( argv, options && normalizeConfig("api", options, constant.detailedOptionMap) ) ); + + logger.debug( + `applied config-precedence (${argv["config-precedence"]}): ` + + `${JSON.stringify(appliedOptions)}` + ); + return appliedOptions; } function parseArgsToOptions(argv, overrideDefaults) { @@ -199,7 +219,7 @@ function applyConfigPrecedence(argv, options) { return options || parseArgsToOptions(argv); } } catch (error) { - console.error(error.toString()); + logger.error(error.toString()); process.exit(2); } } @@ -235,7 +255,7 @@ function eachFilename(argv, patterns, callback) { ignoreText = fs.readFileSync(ignoreFilePath, "utf8"); } catch (readError) { if (readError.code !== "ENOENT") { - console.error(`Unable to read ${ignoreFilePath}:`, readError); + logger.error(`Unable to read ${ignoreFilePath}: ` + readError.message); process.exit(2); } } @@ -252,7 +272,7 @@ function eachFilename(argv, patterns, callback) { .map(filePath => path.relative(process.cwd(), filePath)); if (filePaths.length === 0) { - console.error(`No matching files. Patterns tried: ${patterns.join(" ")}`); + logger.error(`No matching files. Patterns tried: ${patterns.join(" ")}`); process.exitCode = 2; return; } @@ -262,8 +282,8 @@ function eachFilename(argv, patterns, callback) { callback(filePath, getOptionsForFile(argv, filePath)) ); } catch (error) { - console.error( - `Unable to expand glob patterns: ${patterns.join(" ")}\n${error}` + logger.error( + `Unable to expand glob patterns: ${patterns.join(" ")}\n${error.message}` ); // Don't exit the process if one pattern failed process.exitCode = 2; @@ -284,7 +304,7 @@ function formatFiles(argv) { // Add newline to split errors from filename line. process.stdout.write("\n"); - console.error(`Unable to read file: ${filename}\n${error}`); + logger.error(`Unable to read file: ${filename}\n${error.message}`); // Don't exit the process if one file failed process.exitCode = 2; return; @@ -335,7 +355,7 @@ function formatFiles(argv) { try { fs.writeFileSync(filename, output, "utf8"); } catch (error) { - console.error(`Unable to write file: ${filename}\n${error}`); + logger.error(`Unable to write file: ${filename}\n${error.message}`); // Don't exit the process if one file failed process.exitCode = 2; } @@ -470,14 +490,14 @@ function getOptionWithLevenSuggestion(options, optionName) { if (suggestedOptionNameContainer !== undefined) { const suggestedOptionName = suggestedOptionNameContainer.value; - console.warn( - `Unknown option name "${optionName}", did you mean "${suggestedOptionName}"?\n` + logger.warn( + `Unknown option name "${optionName}", did you mean "${suggestedOptionName}"?` ); return options[suggestedOptionNameContainer.index]; } - console.warn(`Unknown option name "${optionName}"\n`); + logger.warn(`Unknown option name "${optionName}"`); return options.find(option => option.name === "help"); } @@ -562,7 +582,8 @@ function normalizeConfig(type, rawConfig, options) { options = options || {}; - const consoleWarn = options.warning === false ? () => {} : console.warn; + const consoleWarn = + options.warning === false ? () => {} : logger.warn.bind(logger); const normalized = {}; @@ -585,11 +606,12 @@ function normalizeConfig(type, rawConfig, options) { // unknown option if (option === undefined) { - // no need to warn for CLI since it's already warned in minimist if (type === "api") { - console.warn(`Ignored unknown option: ${rawKey}`); + consoleWarn(`Ignored unknown option: ${rawKey}`); + } else { + const optionName = rawValue === false ? `no-${rawKey}` : rawKey; + consoleWarn(`Ignored unknown option: --${optionName}`); } - return; } @@ -609,18 +631,23 @@ function normalizeConfig(type, rawConfig, options) { } } - switch (option.type) { - case "int": - validator.validateIntOption(type, value, option); - normalized[rawKey] = Number(value); - break; - case "choice": - validator.validateChoiceOption(type, value, option); - normalized[rawKey] = value; - break; - default: - normalized[rawKey] = value; - break; + try { + switch (option.type) { + case "int": + validator.validateIntOption(type, value, option); + normalized[rawKey] = Number(value); + break; + case "choice": + validator.validateChoiceOption(type, value, option); + normalized[rawKey] = value; + break; + default: + normalized[rawKey] = value; + break; + } + } catch (error) { + logger.error(error.message); + process.exit(2); } }); diff --git a/src/cli-validator.js b/src/cli-validator.js index 59bd7ef3..a5aa2770 100644 --- a/src/cli-validator.js +++ b/src/cli-validator.js @@ -1,15 +1,16 @@ "use strict"; const camelCase = require("camelcase"); +const logger = require("./cli-logger"); function validateArgv(argv) { if (argv["write"] && argv["debug-check"]) { - console.error("Cannot use --write and --debug-check together."); + logger.error("Cannot use --write and --debug-check together."); process.exit(1); } if (argv["find-config-path"] && argv.__filePatterns.length) { - console.error("Cannot use --find-config-path with multiple files"); + logger.error("Cannot use --find-config-path with multiple files"); process.exit(1); } } diff --git a/src/cli.js b/src/cli.js index ed8b8ce1..beb7b020 100644 --- a/src/cli.js +++ b/src/cli.js @@ -6,12 +6,17 @@ const prettier = eval("require")("../index"); const constant = require("./cli-constant"); const util = require("./cli-util"); const validator = require("./cli-validator"); +const logger = require("./cli-logger"); function run(args) { - const argv = util.normalizeConfig( - "cli", - minimist(args, constant.minimistOptions) - ); + const rawArgv = minimist(args, constant.minimistOptions); + + process.env[logger.ENV_LOG_LEVEL] = + rawArgv["loglevel"] || constant.detailedOptionMap["loglevel"].default; + + const argv = util.normalizeConfig("cli", rawArgv); + + logger.debug(`normalized argv: ${JSON.stringify(argv)}`); argv.__args = args; argv.__filePatterns = argv["_"]; diff --git a/tests_integration/__tests__/__snapshots__/arg-parsing.js.snap b/tests_integration/__tests__/__snapshots__/arg-parsing.js.snap index 91b0c411..bbe7241a 100644 --- a/tests_integration/__tests__/__snapshots__/arg-parsing.js.snap +++ b/tests_integration/__tests__/__snapshots__/arg-parsing.js.snap @@ -10,7 +10,7 @@ exports[`boolean flags do not swallow the next argument (stdout) 1`] = ` exports[`boolean flags do not swallow the next argument (write) 1`] = `Array []`; exports[`deprecated option values are warned (stderr) 1`] = ` -"\`--trailing-comma\` without an argument is deprecated. Prettier now treats it as: \`--trailing-comma=es5\`. +"[warn] \`--trailing-comma\` without an argument is deprecated. Prettier now treats it as: \`--trailing-comma=es5\`. " `; @@ -22,7 +22,7 @@ exports[`deprecated option values are warned (stdout) 1`] = ` exports[`deprecated option values are warned (write) 1`] = `Array []`; exports[`deprecated options are warned (stderr) 1`] = ` -"\`--flow-parser\` is deprecated. Use \`--parser flow\` instead. +"[warn] \`--flow-parser\` is deprecated. Use \`--parser flow\` instead. " `; @@ -43,8 +43,7 @@ exports[`negated options work (stdout) 1`] = ` exports[`negated options work (write) 1`] = `Array []`; exports[`unknown negated options are warned (stderr) 1`] = ` -"Ignored unknown option: --no-unknown - +"[warn] Ignored unknown option: --no-unknown " `; @@ -56,8 +55,7 @@ exports[`unknown negated options are warned (stdout) 1`] = ` exports[`unknown negated options are warned (write) 1`] = `Array []`; exports[`unknown options are warned (stderr) 1`] = ` -"Ignored unknown option: --unknown - +"[warn] Ignored unknown option: --unknown " `; diff --git a/tests_integration/__tests__/__snapshots__/config-invalid.js.snap b/tests_integration/__tests__/__snapshots__/config-invalid.js.snap index 78524a69..66da7b9f 100644 --- a/tests_integration/__tests__/__snapshots__/config-invalid.js.snap +++ b/tests_integration/__tests__/__snapshots__/config-invalid.js.snap @@ -1,7 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`show warning with unknown option (stderr) 1`] = ` -"Ignored unknown option: hello +"[warn] Ignored unknown option: hello " `; @@ -10,8 +10,7 @@ exports[`show warning with unknown option (stdout) 1`] = `""`; exports[`show warning with unknown option (write) 1`] = `Array []`; exports[`throw error with invalid config format (stderr) 1`] = ` -"Error: Invalid configuration file. -Failed to parse \\"/tests_integration/cli/config/invalid/file/.prettierrc\\" as JSON, JS, or YAML. +"[error] Invalid configuration file: Failed to parse \\"/tests_integration/cli/config/invalid/file/.prettierrc\\" as JSON, JS, or YAML. " `; @@ -20,8 +19,9 @@ exports[`throw error with invalid config format (stdout) 1`] = `""`; exports[`throw error with invalid config format (write) 1`] = `Array []`; exports[`throw error with invalid config option (int) (stderr) 1`] = ` -"Invalid tabWidth value. -Expected an integer, but received: 0.5" +"[error] Invalid tabWidth value. +[error] Expected an integer, but received: 0.5 +" `; exports[`throw error with invalid config option (int) (stdout) 1`] = `""`; @@ -29,8 +29,9 @@ exports[`throw error with invalid config option (int) (stdout) 1`] = `""`; exports[`throw error with invalid config option (int) (write) 1`] = `Array []`; exports[`throw error with invalid config option (trailingComma) (stderr) 1`] = ` -"Invalid option for trailingComma. -Expected \\"none\\", \\"es5\\" or \\"all\\", but received: \\"wow\\"" +"[error] Invalid option for trailingComma. +[error] Expected \\"none\\", \\"es5\\" or \\"all\\", but received: \\"wow\\" +" `; exports[`throw error with invalid config option (trailingComma) (stdout) 1`] = `""`; @@ -38,8 +39,9 @@ exports[`throw error with invalid config option (trailingComma) (stdout) 1`] = ` exports[`throw error with invalid config option (trailingComma) (write) 1`] = `Array []`; exports[`throw error with invalid config precedence option (configPrecedence) (stderr) 1`] = ` -"Invalid option for --config-precedence. -Expected \\"cli-override\\", \\"file-override\\" or \\"prefer-file\\", but received: \\"option/configPrecedence\\"" +"[error] Invalid option for --config-precedence. +[error] Expected \\"cli-override\\", \\"file-override\\" or \\"prefer-file\\", but received: \\"option/configPrecedence\\" +" `; exports[`throw error with invalid config precedence option (configPrecedence) (stdout) 1`] = `""`; @@ -47,8 +49,7 @@ exports[`throw error with invalid config precedence option (configPrecedence) (s exports[`throw error with invalid config precedence option (configPrecedence) (write) 1`] = `Array []`; exports[`throw error with invalid config target (directory) (stderr) 1`] = ` -"Error: Invalid configuration file. -EISDIR: illegal operation on a directory, read +"[error] Invalid configuration file: EISDIR: illegal operation on a directory, read " `; diff --git a/tests_integration/__tests__/__snapshots__/debug-check.js.snap b/tests_integration/__tests__/__snapshots__/debug-check.js.snap index 1a9a5815..28cc9e70 100644 --- a/tests_integration/__tests__/__snapshots__/debug-check.js.snap +++ b/tests_integration/__tests__/__snapshots__/debug-check.js.snap @@ -5,56 +5,56 @@ exports[`checks stdin with --debug-check (write) 1`] = `Array []`; exports[`doesn't crash when --debug-check is passed (write) 1`] = `Array []`; exports[`show diff for 2+ error files with --debug-check (stderr) 1`] = ` -"a.js: ast(input) !== ast(prettier(input)) -Index: -=================================================================== ---- -+++ -@@ -17,6 +17,6 @@ - \\"method\\": false, - \\"key\\": { -- \\"type\\": \\"StringLiteral\\", -- \\"value\\": \\"a\\" -+ \\"type\\": \\"Identifier\\", -+ \\"name\\": \\"a\\" - }, - \\"computed\\": false, - -Index: -=================================================================== ---- -+++ -@@ -1,3 +1,3 @@ - const a = { -- 'a': 1 -+ a: 1 - }; - -b.js: ast(input) !== ast(prettier(input)) -Index: -=================================================================== ---- -+++ -@@ -17,6 +17,6 @@ - \\"method\\": false, - \\"key\\": { -- \\"type\\": \\"StringLiteral\\", -- \\"value\\": \\"b\\" -+ \\"type\\": \\"Identifier\\", -+ \\"name\\": \\"b\\" - }, - \\"computed\\": false, - -Index: -=================================================================== ---- -+++ -@@ -1,3 +1,3 @@ - const b = { -- 'b': 2 -+ b: 2 - }; - +"[error] a.js: ast(input) !== ast(prettier(input)) +[error] Index: +[error] =================================================================== +[error] --- +[error] +++ +[error] @@ -17,6 +17,6 @@ +[error] \\"method\\": false, +[error] \\"key\\": { +[error] - \\"type\\": \\"StringLiteral\\", +[error] - \\"value\\": \\"a\\" +[error] + \\"type\\": \\"Identifier\\", +[error] + \\"name\\": \\"a\\" +[error] }, +[error] \\"computed\\": false, +[error] +[error] Index: +[error] =================================================================== +[error] --- +[error] +++ +[error] @@ -1,3 +1,3 @@ +[error] const a = { +[error] - 'a': 1 +[error] + a: 1 +[error] }; +[error] +[error] b.js: ast(input) !== ast(prettier(input)) +[error] Index: +[error] =================================================================== +[error] --- +[error] +++ +[error] @@ -17,6 +17,6 @@ +[error] \\"method\\": false, +[error] \\"key\\": { +[error] - \\"type\\": \\"StringLiteral\\", +[error] - \\"value\\": \\"b\\" +[error] + \\"type\\": \\"Identifier\\", +[error] + \\"name\\": \\"b\\" +[error] }, +[error] \\"computed\\": false, +[error] +[error] Index: +[error] =================================================================== +[error] --- +[error] +++ +[error] @@ -1,3 +1,3 @@ +[error] const b = { +[error] - 'b': 2 +[error] + b: 2 +[error] }; +[error] " `; diff --git a/tests_integration/__tests__/__snapshots__/early-exit.js.snap b/tests_integration/__tests__/__snapshots__/early-exit.js.snap index edb62ea7..c13f034c 100644 --- a/tests_integration/__tests__/__snapshots__/early-exit.js.snap +++ b/tests_integration/__tests__/__snapshots__/early-exit.js.snap @@ -155,6 +155,26 @@ exports[`show detailed usage with --help list-different (stdout) 1`] = ` exports[`show detailed usage with --help list-different (write) 1`] = `Array []`; +exports[`show detailed usage with --help loglevel (stderr) 1`] = `""`; + +exports[`show detailed usage with --help loglevel (stdout) 1`] = ` +"--loglevel + + What level of logs to report. + +Valid options: + + silent + error + warn + debug + +Default: warn +" +`; + +exports[`show detailed usage with --help loglevel (write) 1`] = `Array []`; + exports[`show detailed usage with --help no-bracket-spacing (stderr) 1`] = `""`; exports[`show detailed usage with --help no-bracket-spacing (stdout) 1`] = ` @@ -475,6 +495,9 @@ Other options: Example: --help write --insert-pragma Insert @format pragma into file's first docblock comment. Defaults to false. + --loglevel + What level of logs to report. + Defaults to warn. --require-pragma Require either '@prettier' or '@format' to be present in the file's first docblock comment in order for it to be formatted. Defaults to false. @@ -493,8 +516,7 @@ exports[`show version with --version (stderr) 1`] = `""`; exports[`show version with --version (write) 1`] = `Array []`; exports[`show warning with --help not-found (stderr) 1`] = ` -"Unknown option name \\"not-found\\" - +"[warn] Unknown option name \\"not-found\\" " `; @@ -507,8 +529,7 @@ exports[`show warning with --help not-found (stdout) 1`] = ` `; exports[`show warning with --help not-found (typo) (stderr) 1`] = ` -"Unknown option name \\"parserr\\", did you mean \\"parser\\"? - +"[warn] Unknown option name \\"parserr\\", did you mean \\"parser\\"? " `; @@ -605,6 +626,9 @@ Other options: Example: --help write --insert-pragma Insert @format pragma into file's first docblock comment. Defaults to false. + --loglevel + What level of logs to report. + Defaults to warn. --require-pragma Require either '@prettier' or '@format' to be present in the file's first docblock comment in order for it to be formatted. Defaults to false. @@ -619,7 +643,7 @@ Other options: exports[`throw error and show usage with something unexpected (write) 1`] = `Array []`; exports[`throw error with --find-config-path + multiple files (stderr) 1`] = ` -"Cannot use --find-config-path with multiple files +"[error] Cannot use --find-config-path with multiple files " `; @@ -628,7 +652,7 @@ exports[`throw error with --find-config-path + multiple files (stdout) 1`] = `"" exports[`throw error with --find-config-path + multiple files (write) 1`] = `Array []`; exports[`throw error with --write + --debug-check (stderr) 1`] = ` -"Cannot use --write and --debug-check together. +"[error] Cannot use --write and --debug-check together. " `; diff --git a/tests_integration/__tests__/__snapshots__/invalid-ignore.js.snap b/tests_integration/__tests__/__snapshots__/invalid-ignore.js.snap index 1a004e09..382ea50e 100644 --- a/tests_integration/__tests__/__snapshots__/invalid-ignore.js.snap +++ b/tests_integration/__tests__/__snapshots__/invalid-ignore.js.snap @@ -1,7 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`throw error with invalid ignore (stderr) 1`] = ` -"Unable to read /tests_integration/cli/invalid-ignore/.prettierignore: +"[error] Unable to read /tests_integration/cli/invalid-ignore/.prettierignore: EISDIR: illegal operation on a directory, read " `; diff --git a/tests_integration/__tests__/__snapshots__/multiple-patterns.js.snap b/tests_integration/__tests__/__snapshots__/multiple-patterns.js.snap index b9b3acb6..b790ddec 100644 --- a/tests_integration/__tests__/__snapshots__/multiple-patterns.js.snap +++ b/tests_integration/__tests__/__snapshots__/multiple-patterns.js.snap @@ -72,7 +72,7 @@ directory/nested-directory/nested-directory-file.js exports[`multiple patterns with non exists pattern (write) 1`] = `Array []`; exports[`multiple patterns, throw error and exit with non zero code on non existing files (stderr) 1`] = ` -"No matching files. Patterns tried: non-existent.js other-non-existent.js !**/node_modules/** !./node_modules/** +"[error] No matching files. Patterns tried: non-existent.js other-non-existent.js !**/node_modules/** !./node_modules/** " `; diff --git a/tests_integration/__tests__/__snapshots__/stdin-filepath.js.snap b/tests_integration/__tests__/__snapshots__/stdin-filepath.js.snap index 6041b6c6..f94c00c3 100644 --- a/tests_integration/__tests__/__snapshots__/stdin-filepath.js.snap +++ b/tests_integration/__tests__/__snapshots__/stdin-filepath.js.snap @@ -12,9 +12,9 @@ exports[`format correctly if stdin content compatible with stdin-filepath (stdou exports[`format correctly if stdin content compatible with stdin-filepath (write) 1`] = `Array []`; exports[`throw error if stdin content incompatible with stdin-filepath (stderr) 1`] = ` -"stdin: SyntaxError: Unexpected token (1:1) -> 1 | .name { display: none; } - | ^ +"[error] stdin: SyntaxError: Unexpected token (1:1) +[error] > 1 | .name { display: none; } +[error] | ^ " `; diff --git a/tests_integration/__tests__/__snapshots__/syntax-error.js.snap b/tests_integration/__tests__/__snapshots__/syntax-error.js.snap index efc4f61d..31221550 100644 --- a/tests_integration/__tests__/__snapshots__/syntax-error.js.snap +++ b/tests_integration/__tests__/__snapshots__/syntax-error.js.snap @@ -1,9 +1,9 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`exits with non-zero code when input has a syntax error (stderr) 1`] = ` -"stdin: SyntaxError: Unexpected token, expected ; (1:2) -> 1 | a.2 - | ^ +"[error] stdin: SyntaxError: Unexpected token, expected ; (1:2) +[error] > 1 | a.2 +[error] | ^ " `; diff --git a/tests_integration/__tests__/__snapshots__/with-config-precedence.js.snap b/tests_integration/__tests__/__snapshots__/with-config-precedence.js.snap index 28efd980..03eb6f6c 100644 --- a/tests_integration/__tests__/__snapshots__/with-config-precedence.js.snap +++ b/tests_integration/__tests__/__snapshots__/with-config-precedence.js.snap @@ -192,8 +192,9 @@ function rcYaml() { exports[`CLI overrides take precedence without --config-precedence (write) 1`] = `Array []`; exports[`CLI validate options with --config-precedence cli-override (stderr) 1`] = ` -"Invalid printWidth value. -Expected an integer, but received: 0.5" +"[error] Invalid printWidth value. +[error] Expected an integer, but received: 0.5 +" `; exports[`CLI validate options with --config-precedence cli-override (stdout) 1`] = `""`; @@ -201,8 +202,9 @@ exports[`CLI validate options with --config-precedence cli-override (stdout) 1`] exports[`CLI validate options with --config-precedence cli-override (write) 1`] = `Array []`; exports[`CLI validate options with --config-precedence file-override (stderr) 1`] = ` -"Invalid printWidth value. -Expected an integer, but received: 0.5" +"[error] Invalid printWidth value. +[error] Expected an integer, but received: 0.5 +" `; exports[`CLI validate options with --config-precedence file-override (stdout) 1`] = `""`; @@ -210,8 +212,9 @@ exports[`CLI validate options with --config-precedence file-override (stdout) 1` exports[`CLI validate options with --config-precedence file-override (write) 1`] = `Array []`; exports[`CLI validate options with --config-precedence prefer-file (stderr) 1`] = ` -"Invalid printWidth value. -Expected an integer, but received: 0.5" +"[error] Invalid printWidth value. +[error] Expected an integer, but received: 0.5 +" `; exports[`CLI validate options with --config-precedence prefer-file (stdout) 1`] = `""`; diff --git a/tests_integration/__tests__/__snapshots__/write.js.snap b/tests_integration/__tests__/__snapshots__/write.js.snap index 5b2b7c90..e7ca20f2 100644 --- a/tests_integration/__tests__/__snapshots__/write.js.snap +++ b/tests_integration/__tests__/__snapshots__/write.js.snap @@ -8,9 +8,9 @@ exports[`do not write file with --write + formatted file (stdout) 1`] = ` `; exports[`do not write file with --write + invalid file (stderr) 1`] = ` -"invalid.js: SyntaxError: Unexpected token, expected ; (1:6) -> 1 | this is invalid! - | ^ +"[error] invalid.js: SyntaxError: Unexpected token, expected ; (1:6) +[error] > 1 | this is invalid! +[error] | ^ " `; diff --git a/tests_integration/__tests__/loglevel.js b/tests_integration/__tests__/loglevel.js new file mode 100644 index 00000000..d6d38088 --- /dev/null +++ b/tests_integration/__tests__/loglevel.js @@ -0,0 +1,40 @@ +"use strict"; + +const runPrettier = require("../runPrettier"); + +test("do not show logs with --loglevel silent", () => { + runPrettierWithLogLevel("silent", null); +}); + +test("do not show warnings with --loglevel error", () => { + runPrettierWithLogLevel("error", ["[error]"]); +}); + +test("show errors and warnings with --loglevel warn", () => { + runPrettierWithLogLevel("warn", ["[error]", "[warn]"]); +}); + +test("show all logs with --loglevel debug", () => { + runPrettierWithLogLevel("debug", ["[error]", "[warn]", "[debug]"]); +}); + +function runPrettierWithLogLevel(logLevel, patterns) { + const result = runPrettier("cli/loglevel", [ + "--loglevel", + logLevel, + "--unknown-option", + "--parser", + "unknown-parser", + "not-found.js" + ]); + + expect(result).not.toEqual(0); + + if (patterns) { + patterns.forEach(pattern => { + expect(result.stderr).toMatch(pattern); + }); + } else { + expect(result.stderr).toMatch(/^\s*$/); + } +} diff --git a/tests_integration/cli/loglevel/.prettierrc b/tests_integration/cli/loglevel/.prettierrc new file mode 100644 index 00000000..02e89d4d --- /dev/null +++ b/tests_integration/cli/loglevel/.prettierrc @@ -0,0 +1,3 @@ +{ + "printWidth": 999 +} \ No newline at end of file diff --git a/tests_integration/runPrettier.js b/tests_integration/runPrettier.js index d74fb5fb..55ea50cd 100644 --- a/tests_integration/runPrettier.js +++ b/tests_integration/runPrettier.js @@ -3,6 +3,7 @@ const fs = require("fs"); const path = require("path"); const stripAnsi = require("strip-ansi"); +const ENV_LOG_LEVEL = require("../src/cli-logger").ENV_LOG_LEVEL; const isProduction = process.env.NODE_ENV === "production"; const prettierApi = isProduction ? "../dist/index" : "../index"; @@ -55,6 +56,7 @@ function runPrettier(dir, args, options) { const originalExitCode = process.exitCode; const originalStdinIsTTY = process.stdin.isTTY; const originalStdoutIsTTY = process.stdout.isTTY; + const originalEnvLogLevel = process.env[ENV_LOG_LEVEL]; process.chdir(normalizeDir(dir)); process.stdin.isTTY = !!options.isTTY; @@ -84,6 +86,7 @@ function runPrettier(dir, args, options) { process.exitCode = originalExitCode; process.stdin.isTTY = originalStdinIsTTY; process.stdout.isTTY = originalStdoutIsTTY; + process.env[ENV_LOG_LEVEL] = originalEnvLogLevel; jest.restoreAllMocks(); } @@ -113,7 +116,7 @@ function runPrettier(dir, args, options) { return result; }; - return { test: testResult }; + return Object.assign({ test: testResult }, result); function appendStdout(text) { if (status === undefined) {