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
master
Ika 2017-10-13 20:17:01 -05:00 committed by GitHub
parent db0f2ee428
commit 2ef879f20d
18 changed files with 293 additions and 140 deletions

View File

@ -187,6 +187,12 @@ const detailedOptions = normalizeDetailedOptions({
description: description:
"Print the names of files that are different from Prettier's formatting." "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: { parser: {
type: "choice", type: "choice",
category: CATEGORY_FORMAT, category: CATEGORY_FORMAT,
@ -334,13 +340,7 @@ const minimistOptions = {
(current, option) => (current, option) =>
Object.assign({ [option.name]: option.alias }, current), Object.assign({ [option.name]: option.alias }, current),
{} {}
), )
unknown: param => {
if (param.startsWith("-")) {
console.warn(`Ignored unknown option: ${param}\n`);
return false;
}
}
}; };
const usageSummary = ` const usageSummary = `

48
src/cli-logger.js Normal file
View File

@ -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
};

View File

@ -18,6 +18,7 @@ const constant = require("./cli-constant");
const validator = require("./cli-validator"); const validator = require("./cli-validator");
const apiDefaultOptions = require("./options").defaults; const apiDefaultOptions = require("./options").defaults;
const errors = require("./errors"); const errors = require("./errors");
const logger = require("./cli-logger");
const OPTION_USAGE_THRESHOLD = 25; const OPTION_USAGE_THRESHOLD = 25;
const CHOICE_USAGE_MARGIN = 3; 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 // `util.inspect` of throws things that aren't `Error` objects. (The Flow
// parser has mistakenly thrown arrays sometimes.) // parser has mistakenly thrown arrays sometimes.)
if (isParseError) { if (isParseError) {
console.error(`${filename}: ${String(error)}`); logger.error(`${filename}: ${String(error)}`);
} else if (isValidationError || error instanceof errors.ConfigError) { } 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. // If validation fails for one file, it will fail for all of them.
process.exit(1); process.exit(1);
} else if (error instanceof errors.DebugError) { } else if (error instanceof errors.DebugError) {
console.error(`${filename}: ${error.message}`); logger.error(`${filename}: ${error.message}`);
} else { } else {
console.error(filename + ":", error.stack || error); logger.error(filename + ": " + (error.stack || error));
} }
// Don't exit the process if one file failed // Don't exit the process if one file failed
@ -146,25 +147,44 @@ function format(argv, input, opt) {
function getOptionsOrDie(argv, filePath) { function getOptionsOrDie(argv, filePath) {
try { try {
return argv["config"] === false if (argv["config"] === false) {
? null logger.debug("'--no-config' option found, skip loading config file.");
: resolver.resolveConfig.sync(filePath, { config: argv["config"] }); 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) { } catch (error) {
console.error("Error: Invalid configuration file."); logger.error("Invalid configuration file: " + error.message);
console.error(error.message);
process.exit(2); process.exit(2);
} }
} }
function getOptionsForFile(argv, filepath) { function getOptionsForFile(argv, filepath) {
const options = getOptionsOrDie(argv, filepath); const options = getOptionsOrDie(argv, filepath);
return Object.assign(
const appliedOptions = Object.assign(
{ filepath }, { filepath },
applyConfigPrecedence( applyConfigPrecedence(
argv, argv,
options && normalizeConfig("api", options, constant.detailedOptionMap) options && normalizeConfig("api", options, constant.detailedOptionMap)
) )
); );
logger.debug(
`applied config-precedence (${argv["config-precedence"]}): ` +
`${JSON.stringify(appliedOptions)}`
);
return appliedOptions;
} }
function parseArgsToOptions(argv, overrideDefaults) { function parseArgsToOptions(argv, overrideDefaults) {
@ -199,7 +219,7 @@ function applyConfigPrecedence(argv, options) {
return options || parseArgsToOptions(argv); return options || parseArgsToOptions(argv);
} }
} catch (error) { } catch (error) {
console.error(error.toString()); logger.error(error.toString());
process.exit(2); process.exit(2);
} }
} }
@ -235,7 +255,7 @@ function eachFilename(argv, patterns, callback) {
ignoreText = fs.readFileSync(ignoreFilePath, "utf8"); ignoreText = fs.readFileSync(ignoreFilePath, "utf8");
} catch (readError) { } catch (readError) {
if (readError.code !== "ENOENT") { if (readError.code !== "ENOENT") {
console.error(`Unable to read ${ignoreFilePath}:`, readError); logger.error(`Unable to read ${ignoreFilePath}: ` + readError.message);
process.exit(2); process.exit(2);
} }
} }
@ -252,7 +272,7 @@ function eachFilename(argv, patterns, callback) {
.map(filePath => path.relative(process.cwd(), filePath)); .map(filePath => path.relative(process.cwd(), filePath));
if (filePaths.length === 0) { 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; process.exitCode = 2;
return; return;
} }
@ -262,8 +282,8 @@ function eachFilename(argv, patterns, callback) {
callback(filePath, getOptionsForFile(argv, filePath)) callback(filePath, getOptionsForFile(argv, filePath))
); );
} catch (error) { } catch (error) {
console.error( logger.error(
`Unable to expand glob patterns: ${patterns.join(" ")}\n${error}` `Unable to expand glob patterns: ${patterns.join(" ")}\n${error.message}`
); );
// Don't exit the process if one pattern failed // Don't exit the process if one pattern failed
process.exitCode = 2; process.exitCode = 2;
@ -284,7 +304,7 @@ function formatFiles(argv) {
// Add newline to split errors from filename line. // Add newline to split errors from filename line.
process.stdout.write("\n"); 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 // Don't exit the process if one file failed
process.exitCode = 2; process.exitCode = 2;
return; return;
@ -335,7 +355,7 @@ function formatFiles(argv) {
try { try {
fs.writeFileSync(filename, output, "utf8"); fs.writeFileSync(filename, output, "utf8");
} catch (error) { } 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 // Don't exit the process if one file failed
process.exitCode = 2; process.exitCode = 2;
} }
@ -470,14 +490,14 @@ function getOptionWithLevenSuggestion(options, optionName) {
if (suggestedOptionNameContainer !== undefined) { if (suggestedOptionNameContainer !== undefined) {
const suggestedOptionName = suggestedOptionNameContainer.value; const suggestedOptionName = suggestedOptionNameContainer.value;
console.warn( logger.warn(
`Unknown option name "${optionName}", did you mean "${suggestedOptionName}"?\n` `Unknown option name "${optionName}", did you mean "${suggestedOptionName}"?`
); );
return options[suggestedOptionNameContainer.index]; return options[suggestedOptionNameContainer.index];
} }
console.warn(`Unknown option name "${optionName}"\n`); logger.warn(`Unknown option name "${optionName}"`);
return options.find(option => option.name === "help"); return options.find(option => option.name === "help");
} }
@ -562,7 +582,8 @@ function normalizeConfig(type, rawConfig, options) {
options = options || {}; options = options || {};
const consoleWarn = options.warning === false ? () => {} : console.warn; const consoleWarn =
options.warning === false ? () => {} : logger.warn.bind(logger);
const normalized = {}; const normalized = {};
@ -585,11 +606,12 @@ function normalizeConfig(type, rawConfig, options) {
// unknown option // unknown option
if (option === undefined) { if (option === undefined) {
// no need to warn for CLI since it's already warned in minimist
if (type === "api") { 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; return;
} }
@ -609,6 +631,7 @@ function normalizeConfig(type, rawConfig, options) {
} }
} }
try {
switch (option.type) { switch (option.type) {
case "int": case "int":
validator.validateIntOption(type, value, option); validator.validateIntOption(type, value, option);
@ -622,6 +645,10 @@ function normalizeConfig(type, rawConfig, options) {
normalized[rawKey] = value; normalized[rawKey] = value;
break; break;
} }
} catch (error) {
logger.error(error.message);
process.exit(2);
}
}); });
return normalized; return normalized;

View File

@ -1,15 +1,16 @@
"use strict"; "use strict";
const camelCase = require("camelcase"); const camelCase = require("camelcase");
const logger = require("./cli-logger");
function validateArgv(argv) { function validateArgv(argv) {
if (argv["write"] && argv["debug-check"]) { 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); process.exit(1);
} }
if (argv["find-config-path"] && argv.__filePatterns.length) { 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); process.exit(1);
} }
} }

View File

@ -6,12 +6,17 @@ const prettier = eval("require")("../index");
const constant = require("./cli-constant"); const constant = require("./cli-constant");
const util = require("./cli-util"); const util = require("./cli-util");
const validator = require("./cli-validator"); const validator = require("./cli-validator");
const logger = require("./cli-logger");
function run(args) { function run(args) {
const argv = util.normalizeConfig( const rawArgv = minimist(args, constant.minimistOptions);
"cli",
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.__args = args;
argv.__filePatterns = argv["_"]; argv.__filePatterns = argv["_"];

View File

@ -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[`boolean flags do not swallow the next argument (write) 1`] = `Array []`;
exports[`deprecated option values are warned (stderr) 1`] = ` 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 option values are warned (write) 1`] = `Array []`;
exports[`deprecated options are warned (stderr) 1`] = ` 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[`negated options work (write) 1`] = `Array []`;
exports[`unknown negated options are warned (stderr) 1`] = ` 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 negated options are warned (write) 1`] = `Array []`;
exports[`unknown options are warned (stderr) 1`] = ` exports[`unknown options are warned (stderr) 1`] = `
"Ignored unknown option: --unknown "[warn] Ignored unknown option: --unknown
" "
`; `;

View File

@ -1,7 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`show warning with unknown option (stderr) 1`] = ` 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[`show warning with unknown option (write) 1`] = `Array []`;
exports[`throw error with invalid config format (stderr) 1`] = ` exports[`throw error with invalid config format (stderr) 1`] = `
"Error: Invalid configuration file. "[error] Invalid configuration file: Failed to parse \\"<cwd>/tests_integration/cli/config/invalid/file/.prettierrc\\" as JSON, JS, or YAML.
Failed to parse \\"<cwd>/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 format (write) 1`] = `Array []`;
exports[`throw error with invalid config option (int) (stderr) 1`] = ` exports[`throw error with invalid config option (int) (stderr) 1`] = `
"Invalid tabWidth value. "[error] Invalid tabWidth value.
Expected an integer, but received: 0.5" [error] Expected an integer, but received: 0.5
"
`; `;
exports[`throw error with invalid config option (int) (stdout) 1`] = `""`; 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 (int) (write) 1`] = `Array []`;
exports[`throw error with invalid config option (trailingComma) (stderr) 1`] = ` exports[`throw error with invalid config option (trailingComma) (stderr) 1`] = `
"Invalid option for trailingComma. "[error] Invalid option for trailingComma.
Expected \\"none\\", \\"es5\\" or \\"all\\", but received: \\"wow\\"" [error] Expected \\"none\\", \\"es5\\" or \\"all\\", but received: \\"wow\\"
"
`; `;
exports[`throw error with invalid config option (trailingComma) (stdout) 1`] = `""`; 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 option (trailingComma) (write) 1`] = `Array []`;
exports[`throw error with invalid config precedence option (configPrecedence) (stderr) 1`] = ` exports[`throw error with invalid config precedence option (configPrecedence) (stderr) 1`] = `
"Invalid option for --config-precedence. "[error] Invalid option for --config-precedence.
Expected \\"cli-override\\", \\"file-override\\" or \\"prefer-file\\", but received: \\"option/configPrecedence\\"" [error] Expected \\"cli-override\\", \\"file-override\\" or \\"prefer-file\\", but received: \\"option/configPrecedence\\"
"
`; `;
exports[`throw error with invalid config precedence option (configPrecedence) (stdout) 1`] = `""`; 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 precedence option (configPrecedence) (write) 1`] = `Array []`;
exports[`throw error with invalid config target (directory) (stderr) 1`] = ` exports[`throw error with invalid config target (directory) (stderr) 1`] = `
"Error: Invalid configuration file. "[error] Invalid configuration file: EISDIR: illegal operation on a directory, read
EISDIR: illegal operation on a directory, read
" "
`; `;

View File

@ -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[`doesn't crash when --debug-check is passed (write) 1`] = `Array []`;
exports[`show diff for 2+ error files with --debug-check (stderr) 1`] = ` exports[`show diff for 2+ error files with --debug-check (stderr) 1`] = `
"a.js: ast(input) !== ast(prettier(input)) "[error] a.js: ast(input) !== ast(prettier(input))
Index: [error] Index:
=================================================================== [error] ===================================================================
--- [error] ---
+++ [error] +++
@@ -17,6 +17,6 @@ [error] @@ -17,6 +17,6 @@
\\"method\\": false, [error] \\"method\\": false,
\\"key\\": { [error] \\"key\\": {
- \\"type\\": \\"StringLiteral\\", [error] - \\"type\\": \\"StringLiteral\\",
- \\"value\\": \\"a\\" [error] - \\"value\\": \\"a\\"
+ \\"type\\": \\"Identifier\\", [error] + \\"type\\": \\"Identifier\\",
+ \\"name\\": \\"a\\" [error] + \\"name\\": \\"a\\"
}, [error] },
\\"computed\\": false, [error] \\"computed\\": false,
[error]
Index: [error] Index:
=================================================================== [error] ===================================================================
--- [error] ---
+++ [error] +++
@@ -1,3 +1,3 @@ [error] @@ -1,3 +1,3 @@
const a = { [error] const a = {
- 'a': 1 [error] - 'a': 1
+ a: 1 [error] + a: 1
}; [error] };
[error]
b.js: ast(input) !== ast(prettier(input)) [error] b.js: ast(input) !== ast(prettier(input))
Index: [error] Index:
=================================================================== [error] ===================================================================
--- [error] ---
+++ [error] +++
@@ -17,6 +17,6 @@ [error] @@ -17,6 +17,6 @@
\\"method\\": false, [error] \\"method\\": false,
\\"key\\": { [error] \\"key\\": {
- \\"type\\": \\"StringLiteral\\", [error] - \\"type\\": \\"StringLiteral\\",
- \\"value\\": \\"b\\" [error] - \\"value\\": \\"b\\"
+ \\"type\\": \\"Identifier\\", [error] + \\"type\\": \\"Identifier\\",
+ \\"name\\": \\"b\\" [error] + \\"name\\": \\"b\\"
}, [error] },
\\"computed\\": false, [error] \\"computed\\": false,
[error]
Index: [error] Index:
=================================================================== [error] ===================================================================
--- [error] ---
+++ [error] +++
@@ -1,3 +1,3 @@ [error] @@ -1,3 +1,3 @@
const b = { [error] const b = {
- 'b': 2 [error] - 'b': 2
+ b: 2 [error] + b: 2
}; [error] };
[error]
" "
`; `;

View File

@ -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 list-different (write) 1`] = `Array []`;
exports[`show detailed usage with --help loglevel (stderr) 1`] = `""`;
exports[`show detailed usage with --help loglevel (stdout) 1`] = `
"--loglevel <silent|error|warn|debug>
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 (stderr) 1`] = `""`;
exports[`show detailed usage with --help no-bracket-spacing (stdout) 1`] = ` exports[`show detailed usage with --help no-bracket-spacing (stdout) 1`] = `
@ -475,6 +495,9 @@ Other options:
Example: --help write Example: --help write
--insert-pragma Insert @format pragma into file's first docblock comment. --insert-pragma Insert @format pragma into file's first docblock comment.
Defaults to false. Defaults to false.
--loglevel <silent|error|warn|debug>
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 --require-pragma Require either '@prettier' or '@format' to be present in the file's first docblock comment
in order for it to be formatted. in order for it to be formatted.
Defaults to false. Defaults to false.
@ -493,8 +516,7 @@ exports[`show version with --version (stderr) 1`] = `""`;
exports[`show version with --version (write) 1`] = `Array []`; exports[`show version with --version (write) 1`] = `Array []`;
exports[`show warning with --help not-found (stderr) 1`] = ` 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`] = ` 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 Example: --help write
--insert-pragma Insert @format pragma into file's first docblock comment. --insert-pragma Insert @format pragma into file's first docblock comment.
Defaults to false. Defaults to false.
--loglevel <silent|error|warn|debug>
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 --require-pragma Require either '@prettier' or '@format' to be present in the file's first docblock comment
in order for it to be formatted. in order for it to be formatted.
Defaults to false. Defaults to false.
@ -619,7 +643,7 @@ Other options:
exports[`throw error and show usage with something unexpected (write) 1`] = `Array []`; exports[`throw error and show usage with something unexpected (write) 1`] = `Array []`;
exports[`throw error with --find-config-path + multiple files (stderr) 1`] = ` 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 --find-config-path + multiple files (write) 1`] = `Array []`;
exports[`throw error with --write + --debug-check (stderr) 1`] = ` exports[`throw error with --write + --debug-check (stderr) 1`] = `
"Cannot use --write and --debug-check together. "[error] Cannot use --write and --debug-check together.
" "
`; `;

View File

@ -1,7 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`throw error with invalid ignore (stderr) 1`] = ` exports[`throw error with invalid ignore (stderr) 1`] = `
"Unable to read <cwd>/tests_integration/cli/invalid-ignore/.prettierignore: "[error] Unable to read <cwd>/tests_integration/cli/invalid-ignore/.prettierignore: EISDIR: illegal operation on a directory, read
" "
`; `;

View File

@ -72,7 +72,7 @@ directory/nested-directory/nested-directory-file.js
exports[`multiple patterns with non exists pattern (write) 1`] = `Array []`; 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`] = ` 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/**
" "
`; `;

View File

@ -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[`format correctly if stdin content compatible with stdin-filepath (write) 1`] = `Array []`;
exports[`throw error if stdin content incompatible with stdin-filepath (stderr) 1`] = ` exports[`throw error if stdin content incompatible with stdin-filepath (stderr) 1`] = `
"stdin: SyntaxError: Unexpected token (1:1) "[error] stdin: SyntaxError: Unexpected token (1:1)
> 1 | .name { display: none; } [error] > 1 | .name { display: none; }
| ^ [error] | ^
" "
`; `;

View File

@ -1,9 +1,9 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`exits with non-zero code when input has a syntax error (stderr) 1`] = ` exports[`exits with non-zero code when input has a syntax error (stderr) 1`] = `
"stdin: SyntaxError: Unexpected token, expected ; (1:2) "[error] stdin: SyntaxError: Unexpected token, expected ; (1:2)
> 1 | a.2 [error] > 1 | a.2
| ^ [error] | ^
" "
`; `;

View File

@ -192,8 +192,9 @@ function rcYaml() {
exports[`CLI overrides take precedence without --config-precedence (write) 1`] = `Array []`; exports[`CLI overrides take precedence without --config-precedence (write) 1`] = `Array []`;
exports[`CLI validate options with --config-precedence cli-override (stderr) 1`] = ` exports[`CLI validate options with --config-precedence cli-override (stderr) 1`] = `
"Invalid printWidth value. "[error] Invalid printWidth value.
Expected an integer, but received: 0.5" [error] Expected an integer, but received: 0.5
"
`; `;
exports[`CLI validate options with --config-precedence cli-override (stdout) 1`] = `""`; 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 cli-override (write) 1`] = `Array []`;
exports[`CLI validate options with --config-precedence file-override (stderr) 1`] = ` exports[`CLI validate options with --config-precedence file-override (stderr) 1`] = `
"Invalid printWidth value. "[error] Invalid printWidth value.
Expected an integer, but received: 0.5" [error] Expected an integer, but received: 0.5
"
`; `;
exports[`CLI validate options with --config-precedence file-override (stdout) 1`] = `""`; 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 file-override (write) 1`] = `Array []`;
exports[`CLI validate options with --config-precedence prefer-file (stderr) 1`] = ` exports[`CLI validate options with --config-precedence prefer-file (stderr) 1`] = `
"Invalid printWidth value. "[error] Invalid printWidth value.
Expected an integer, but received: 0.5" [error] Expected an integer, but received: 0.5
"
`; `;
exports[`CLI validate options with --config-precedence prefer-file (stdout) 1`] = `""`; exports[`CLI validate options with --config-precedence prefer-file (stdout) 1`] = `""`;

View File

@ -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`] = ` exports[`do not write file with --write + invalid file (stderr) 1`] = `
"invalid.js: SyntaxError: Unexpected token, expected ; (1:6) "[error] invalid.js: SyntaxError: Unexpected token, expected ; (1:6)
> 1 | this is invalid! [error] > 1 | this is invalid!
| ^ [error] | ^
" "
`; `;

View File

@ -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*$/);
}
}

View File

@ -0,0 +1,3 @@
{
"printWidth": 999
}

View File

@ -3,6 +3,7 @@
const fs = require("fs"); const fs = require("fs");
const path = require("path"); const path = require("path");
const stripAnsi = require("strip-ansi"); const stripAnsi = require("strip-ansi");
const ENV_LOG_LEVEL = require("../src/cli-logger").ENV_LOG_LEVEL;
const isProduction = process.env.NODE_ENV === "production"; const isProduction = process.env.NODE_ENV === "production";
const prettierApi = isProduction ? "../dist/index" : "../index"; const prettierApi = isProduction ? "../dist/index" : "../index";
@ -55,6 +56,7 @@ function runPrettier(dir, args, options) {
const originalExitCode = process.exitCode; const originalExitCode = process.exitCode;
const originalStdinIsTTY = process.stdin.isTTY; const originalStdinIsTTY = process.stdin.isTTY;
const originalStdoutIsTTY = process.stdout.isTTY; const originalStdoutIsTTY = process.stdout.isTTY;
const originalEnvLogLevel = process.env[ENV_LOG_LEVEL];
process.chdir(normalizeDir(dir)); process.chdir(normalizeDir(dir));
process.stdin.isTTY = !!options.isTTY; process.stdin.isTTY = !!options.isTTY;
@ -84,6 +86,7 @@ function runPrettier(dir, args, options) {
process.exitCode = originalExitCode; process.exitCode = originalExitCode;
process.stdin.isTTY = originalStdinIsTTY; process.stdin.isTTY = originalStdinIsTTY;
process.stdout.isTTY = originalStdoutIsTTY; process.stdout.isTTY = originalStdoutIsTTY;
process.env[ENV_LOG_LEVEL] = originalEnvLogLevel;
jest.restoreAllMocks(); jest.restoreAllMocks();
} }
@ -113,7 +116,7 @@ function runPrettier(dir, args, options) {
return result; return result;
}; };
return { test: testResult }; return Object.assign({ test: testResult }, result);
function appendStdout(text) { function appendStdout(text) {
if (status === undefined) { if (status === undefined) {