From d31ebf4619806ebfdff4333222d29b1ba784809b Mon Sep 17 00:00:00 2001 From: fisker Cheung Date: Fri, 21 Aug 2020 09:43:24 +0800 Subject: [PATCH] Test: Improve coverage (#8811) --- jest.config.js | 8 +- src/cli/expand-patterns.js | 2 + src/cli/util.js | 20 ++- src/common/fast-path.js | 1 + src/common/util.js | 12 ++ src/language-css/loc.js | 11 +- src/language-css/parser-postcss.js | 8 ++ src/language-css/printer-postcss.js | 2 + src/language-css/utils.js | 4 + src/language-graphql/parser-graphql.js | 1 + src/language-graphql/printer-graphql.js | 5 +- src/language-handlebars/parser-glimmer.js | 4 +- src/language-html/parser-html.js | 4 + src/language-html/printer-html.js | 25 ++-- src/language-html/utils.js | 11 +- src/language-js/clean.js | 32 ----- src/language-js/parser-typescript.js | 1 + src/language-js/print/member-chain.js | 1 + src/language-js/printer-estree.js | 3 + src/language-js/utils.js | 2 +- src/language-markdown/index.js | 1 + src/language-markdown/mdx.js | 1 + src/language-markdown/printer-markdown.js | 12 +- src/language-yaml/parser-yaml.js | 19 ++- src/language-yaml/printer-yaml.js | 2 + src/language-yaml/utils.js | 2 + src/main/comments.js | 3 + src/main/core.js | 1 + src/main/multiparser.js | 1 + src/main/options-normalizer.js | 3 + src/main/options.js | 6 + src/main/parser.js | 26 ++-- src/main/range-util.js | 1 + src/utils/front-matter.js | 19 +-- src/utils/line-column-to-index.js | 3 - .../__snapshots__/jsfmt.spec.js.snap | 29 +++++ .../type-extension-definition/jsfmt.spec.js | 1 + .../type-extendsion-syntax.graphql | 8 ++ .../cdata/__snapshots__/jsfmt.spec.js.snap | 9 ++ tests/html/cdata/example.html | 3 + .../srcset/__snapshots__/jsfmt.spec.js.snap | 41 +++++++ tests/html/srcset/invalid.html | 12 ++ tests/html/srcset/jsfmt.spec.js | 1 + tests/js/bom/__snapshots__/jsfmt.spec.js.snap | 26 ++++ tests/js/eol/__snapshots__/jsfmt.spec.js.snap | 109 ++++++++++++++++ tests/js/eol/cursor-and-range.js | 7 ++ .../js/range/__snapshots__/jsfmt.spec.js.snap | 24 ++++ tests/js/range/array.js | 9 ++ .../footnote/__snapshots__/jsfmt.spec.js.snap | 15 +++ tests/markdown/footnote/footnote.md | 1 + .../in-html/__snapshots__/jsfmt.spec.js.snap | 116 ++++++++++++++++++ .../in-html/front-matter-toml.html | 9 ++ .../in-html/front-matter-yaml.html | 9 ++ .../__snapshots__/jsfmt.spec.js.snap | 11 ++ tests/misc/errors/handlebars/invalid.hbs | 2 + tests/misc/errors/handlebars/jsfmt.spec.js | 1 + .../less/__snapshots__/jsfmt.spec.js.snap | 20 ++- ...{inline-comment.js => inline-comment.less} | 0 tests/misc/errors/less/open-double-quote.less | 3 + tests/misc/errors/less/open-sigle-quote.less | 3 + .../v-for/__snapshots__/jsfmt.spec.js.snap | 21 ++++ tests/vue/v-for/invalid.vue | 5 + tests/vue/v-for/jsfmt.spec.js | 1 + .../vue/vue/__snapshots__/jsfmt.spec.js.snap | 24 ++++ tests/vue/vue/attributes.vue | 4 + .../__snapshots__/config-invalid.js.snap | 4 + .../__tests__/__snapshots__/debug-api.js.snap | 16 +++ .../__tests__/__snapshots__/file-info.js.snap | 10 ++ .../__snapshots__/stdin-filepath.js.snap | 22 ++++ tests_integration/__tests__/config-invalid.js | 12 ++ .../__tests__/config-resolution.js | 29 +++++ tests_integration/__tests__/debug-api.js | 44 +++++++ tests_integration/__tests__/file-info.js | 10 ++ tests_integration/__tests__/invalid-ignore.js | 13 ++ .../__tests__/plugin-options-string.js | 15 +++ .../__tests__/resolve-config-file.js | 15 +++ tests_integration/__tests__/stdin-filepath.js | 51 ++++++++ tests_integration/__tests__/third-party.js | 6 +- .../cli/config/invalid/type-error/.prettierrc | 1 + .../overrides-exclude-files/.prettierrc | 19 +++ 80 files changed, 924 insertions(+), 124 deletions(-) create mode 100644 tests/graphql/type-extension-definition/__snapshots__/jsfmt.spec.js.snap create mode 100644 tests/graphql/type-extension-definition/jsfmt.spec.js create mode 100644 tests/graphql/type-extension-definition/type-extendsion-syntax.graphql create mode 100644 tests/html/srcset/__snapshots__/jsfmt.spec.js.snap create mode 100644 tests/html/srcset/invalid.html create mode 100644 tests/html/srcset/jsfmt.spec.js create mode 100644 tests/js/eol/cursor-and-range.js create mode 100644 tests/js/range/array.js create mode 100644 tests/markdown/footnote/footnote.md create mode 100644 tests/misc/embedded_language_formatting/in-html/front-matter-toml.html create mode 100644 tests/misc/embedded_language_formatting/in-html/front-matter-yaml.html create mode 100644 tests/misc/errors/handlebars/__snapshots__/jsfmt.spec.js.snap create mode 100644 tests/misc/errors/handlebars/invalid.hbs create mode 100644 tests/misc/errors/handlebars/jsfmt.spec.js rename tests/misc/errors/less/{inline-comment.js => inline-comment.less} (100%) create mode 100644 tests/misc/errors/less/open-double-quote.less create mode 100644 tests/misc/errors/less/open-sigle-quote.less create mode 100644 tests/vue/v-for/__snapshots__/jsfmt.spec.js.snap create mode 100644 tests/vue/v-for/invalid.vue create mode 100644 tests/vue/v-for/jsfmt.spec.js create mode 100644 tests_integration/__tests__/__snapshots__/debug-api.js.snap create mode 100644 tests_integration/__tests__/debug-api.js create mode 100644 tests_integration/__tests__/resolve-config-file.js create mode 100644 tests_integration/cli/config/invalid/type-error/.prettierrc create mode 100644 tests_integration/cli/config/overrides-exclude-files/.prettierrc diff --git a/jest.config.js b/jest.config.js index 9fa555fa4..2a5171e64 100644 --- a/jest.config.js +++ b/jest.config.js @@ -19,12 +19,8 @@ module.exports = { ? ["/tests_integration/"] : [], collectCoverage: ENABLE_CODE_COVERAGE, - collectCoverageFrom: ["src/**/*.js", "index.js", "!/node_modules/"], - coveragePathIgnorePatterns: [ - "/standalone.js", - "/src/document/doc-debug.js", - "/src/main/massage-ast.js", - ], + collectCoverageFrom: ["/src/**/*.js", "/bin/**/*.js"], + coveragePathIgnorePatterns: ["/src/document/doc-debug.js"], coverageReporters: ["text", "lcov"], moduleNameMapper: { "prettier/local": "/tests_config/require_prettier.js", diff --git a/src/cli/expand-patterns.js b/src/cli/expand-patterns.js index b3034c884..346301ad0 100644 --- a/src/cli/expand-patterns.js +++ b/src/cli/expand-patterns.js @@ -109,7 +109,9 @@ function* expandPatternsInternal(context) { try { result = fastGlob.sync(glob, globOptions); } catch ({ message }) { + /* istanbul ignore next */ yield { error: `${errorMessages.globError[type]}: ${input}\n${message}` }; + /* istanbul ignore next */ continue; } diff --git a/src/cli/util.js b/src/cli/util.js index 3065e69e0..6f963a763 100644 --- a/src/cli/util.js +++ b/src/cli/util.js @@ -61,6 +61,8 @@ function diff(a, b) { function handleError(context, filename, error) { if (error instanceof errors.UndefinedParserError) { + // Can't test on CI, `isTTY()` is always false, see ./is-tty.js + /* istanbul ignore next */ if ((context.argv.write || context.argv["ignore-unknown"]) && isTTY()) { readline.clearLine(process.stdout, 0); readline.cursorTo(process.stdout, 0, null); @@ -96,6 +98,7 @@ function handleError(context, filename, error) { context.logger.error(`${filename}: ${error.message}`); } else { // `invalid.js: Error: Some unexpected error\n[stack trace]` + /* istanbul ignore next */ context.logger.error(filename + ": " + (error.stack || error)); } @@ -364,7 +367,10 @@ function applyConfigPrecedence(context, options) { return options || parseArgsToOptions(context); } } catch (error) { + /* istanbul ignore next */ context.logger.error(error.toString()); + + /* istanbul ignore next */ process.exit(2); } } @@ -467,13 +473,19 @@ function formatFiles(context) { input = fs.readFileSync(filename, "utf8"); } catch (error) { // Add newline to split errors from filename line. + /* istanbul ignore next */ context.logger.log(""); + /* istanbul ignore next */ context.logger.error( `Unable to read file: ${filename}\n${error.message}` ); + // Don't exit the process if one file failed + /* istanbul ignore next */ process.exitCode = 2; + + /* istanbul ignore next */ continue; } @@ -514,16 +526,20 @@ function formatFiles(context) { try { fs.writeFileSync(filename, output, "utf8"); } catch (error) { + /* istanbul ignore next */ context.logger.error( `Unable to write file: ${filename}\n${error.message}` ); + // Don't exit the process if one file failed + /* istanbul ignore next */ process.exitCode = 2; } } else if (!context.argv.check && !context.argv["list-different"]) { context.logger.log(`${chalk.grey(filename)} ${Date.now() - start}ms`); } } else if (context.argv["debug-check"]) { + /* istanbul ignore else */ if (result.filepath) { context.logger.log(result.filepath); } else { @@ -769,8 +785,6 @@ function createLogger(logLevel) { switch (logLevel) { case "silent": return false; - default: - return true; case "debug": if (loggerName === "debug") { return true; @@ -804,6 +818,7 @@ function normalizeDetailedOption(name, option) { deprecated: false, ...(typeof choice === "object" ? choice : { value: choice }), }; + /* istanbul ignore next */ if (newChoice.value === true) { newChoice.value = ""; // backward compatibility for original boolean option } @@ -873,6 +888,7 @@ function createDetailedOptionMap(supportOptions) { forwardToApi: option.name, }; + /* istanbul ignore next */ if (option.deprecated) { delete newOption.forwardToApi; delete newOption.description; diff --git a/src/common/fast-path.js b/src/common/fast-path.js index 3a4a7b157..61b5883d6 100644 --- a/src/common/fast-path.js +++ b/src/common/fast-path.js @@ -144,6 +144,7 @@ class FastPath { let node = this.stack[stackPointer--]; for (const predicate of predicates) { + /* istanbul ignore next */ if (node === undefined) { return false; } diff --git a/src/common/util.js b/src/common/util.js index 528931f69..55b33450f 100644 --- a/src/common/util.js +++ b/src/common/util.js @@ -23,6 +23,7 @@ function skip(chars) { // Allow `skip` functions to be threaded together without having // to check for failures (did someone say monads?). + /* istanbul ignore next */ if (index === false) { return false; } @@ -76,6 +77,7 @@ const skipEverythingButNewLine = skip(/[^\n\r]/); * @returns {number | false} */ function skipInlineComment(text, index) { + /* istanbul ignore next */ if (index === false) { return false; } @@ -96,6 +98,7 @@ function skipInlineComment(text, index) { * @returns {number | false} */ function skipTrailingComment(text, index) { + /* istanbul ignore next */ if (index === false) { return false; } @@ -123,6 +126,8 @@ function skipNewline(text, index, opts) { const atIndex = text.charAt(index); if (backwards) { + // We already replace `\r\n` with `\n` before parsing + /* istanbul ignore next */ if (text.charAt(index - 1) === "\r" && atIndex === "\n") { return index - 2; } @@ -135,6 +140,8 @@ function skipNewline(text, index, opts) { return index - 1; } } else { + // We already replace `\r\n` with `\n` before parsing + /* istanbul ignore next */ if (atIndex === "\r" && text.charAt(index + 1) === "\n") { return index + 2; } @@ -277,6 +284,8 @@ function getNextNonSpaceNonCommentCharacter(text, node, locEnd) { ); } +// Not using, but it's public utils +/* istanbul ignore next */ /** * @param {string} text * @param {number} index @@ -577,6 +586,7 @@ function addCommentHelper(node, comment) { // For some reason, TypeScript parses `// x` inside of JSXText as a comment // We already "print" it via the raw text, we don't need to re-print it as a // comment + /* istanbul ignore next */ if (node.type === "JSXText") { comment.printed = true; } @@ -603,6 +613,8 @@ function addTrailingComment(node, comment) { addCommentHelper(node, comment); } +// Not using +/* istanbul ignore next */ function isWithinParentArrayProperty(path, propertyName) { const node = path.getValue(); const parent = path.getParentNode(); diff --git a/src/language-css/loc.js b/src/language-css/loc.js index 5c2b8acaf..0edf10658 100644 --- a/src/language-css/loc.js +++ b/src/language-css/loc.js @@ -4,13 +4,12 @@ const lineColumnToIndex = require("../utils/line-column-to-index"); const { getLast, skipEverythingButNewLine } = require("../common/util"); function calculateLocStart(node, text) { - if (node.source) { - if (typeof node.source.sourceIndex === "number") { - return node.source.sourceIndex; // value-* nodes have this - } - return lineColumnToIndex(node.source.start, text) - 1; + // value-* nodes have this + if (typeof node.sourceIndex === "number") { + return node.sourceIndex; } - return null; + + return node.source ? lineColumnToIndex(node.source.start, text) - 1 : null; } function calculateLocEnd(node, text) { diff --git a/src/language-css/parser-postcss.js b/src/language-css/parser-postcss.js index 76cb43857..e8e503d49 100644 --- a/src/language-css/parser-postcss.js +++ b/src/language-css/parser-postcss.js @@ -109,6 +109,7 @@ function parseValueNode(valueNode, options) { } parenGroup.close = node; + /* istanbul ignore next */ if (commaGroupStack.length === 1) { throw new Error("Unbalanced parenthesis"); } @@ -270,6 +271,7 @@ function parseMediaQuery(params) { result = mediaParser(params); } catch (e) { // Ignore bad media queries + /* istanbul ignore next */ return { type: "selector-unknown", value: params, @@ -294,6 +296,7 @@ function parseNestedCSS(node, options) { return node; } + /* istanbul ignore next */ if (!node.raws) { node.raws = {}; } @@ -352,10 +355,14 @@ function parseNestedCSS(node, options) { // Ignore LESS mixin declaration if (selector.trim().length > 0) { + // TODO: confirm this code is dead + /* istanbul ignore next */ if (selector.startsWith("@") && selector.endsWith(":")) { return node; } + // TODO: confirm this code is dead + /* istanbul ignore next */ // Ignore LESS mixins if (node.mixin) { node.selector = parseValue(selector, options); @@ -581,6 +588,7 @@ function parseWithParser(parse, text, options) { try { result = parse(text); } catch (e) { + /* istanbul ignore next */ if (typeof e.line !== "number") { throw e; } diff --git a/src/language-css/printer-postcss.js b/src/language-css/printer-postcss.js index 6cdd0f6de..c51479b99 100644 --- a/src/language-css/printer-postcss.js +++ b/src/language-css/printer-postcss.js @@ -941,6 +941,8 @@ function genericPrint(path, options, print) { : line, ]); } + // TODO: confirm this code is dead + /* istanbul ignore next */ case "value-comma": { return concat([node.value, " "]); } diff --git a/src/language-css/utils.js b/src/language-css/utils.js index cac78875a..873142919 100644 --- a/src/language-css/utils.js +++ b/src/language-css/utils.js @@ -175,6 +175,8 @@ function isURLFunctionNode(node) { function isLastNode(path, node) { const parentNode = path.getParentNode(); + + /* istanbul ignore next */ if (!parentNode) { return false; } @@ -186,6 +188,7 @@ function isDetachedRulesetDeclarationNode(node) { // If a Less file ends up being parsed with the SCSS parser, Less // variable declarations will be parsed as atrules with names ending // with a colon, so keep the original case then. + /* istanbul ignore next */ if (!node.selector) { return false; } @@ -261,6 +264,7 @@ function isSCSSControlDirectiveNode(node) { } function isSCSSNestedPropertyNode(node) { + /* istanbul ignore next */ if (!node.selector) { return false; } diff --git a/src/language-graphql/parser-graphql.js b/src/language-graphql/parser-graphql.js index d92d39b9f..d0c801e49 100644 --- a/src/language-graphql/parser-graphql.js +++ b/src/language-graphql/parser-graphql.js @@ -66,6 +66,7 @@ function parse(text /*, parsers, opts*/) { }, }); } else { + /* istanbul ignore next */ throw error; } } diff --git a/src/language-graphql/printer-graphql.js b/src/language-graphql/printer-graphql.js index 22fa0a206..637a4f262 100644 --- a/src/language-graphql/printer-graphql.js +++ b/src/language-graphql/printer-graphql.js @@ -275,10 +275,6 @@ function genericPrint(path, options, print) { ]); } - case "TypeExtensionDefinition": { - return concat(["extend ", path.call(print, "definition")]); - } - case "ObjectTypeExtension": case "ObjectTypeDefinition": { return concat([ @@ -645,6 +641,7 @@ function printComment(commentPath) { return "#" + comment.value.trimEnd(); } + /* istanbul ignore next */ throw new Error("Not a comment: " + JSON.stringify(comment)); } diff --git a/src/language-handlebars/parser-glimmer.js b/src/language-handlebars/parser-glimmer.js index 8fbbe600e..007717e3c 100644 --- a/src/language-handlebars/parser-glimmer.js +++ b/src/language-handlebars/parser-glimmer.js @@ -8,9 +8,9 @@ function parse(text, parsers, options) { let ast; try { ast = glimmer(text, { mode: "codemod" }); - /* istanbul ignore next */ } catch (error) { const matches = error.message.match(/on line (\d+)/); + /* istanbul ignore else */ if (matches) { throw createError(error.message, { start: { line: Number(matches[1]), column: 0 }, @@ -32,9 +32,11 @@ module.exports = { // https://prettier.io/docs/en/plugins.html#parsers // but we need access to the original text to use // `loc.start` and `loc.end` objects to calculate the offset + /* istanbul ignore next */ locStart(node) { return node.loc && node.loc.start; }, + /* istanbul ignore next */ locEnd(node) { return node.loc && node.loc.end; }, diff --git a/src/language-html/parser-html.js b/src/language-html/parser-html.js index bbac18cb6..7b1a93f7d 100644 --- a/src/language-html/parser-html.js +++ b/src/language-html/parser-html.js @@ -59,6 +59,7 @@ function ngHtmlParser( if (options.parser === "vue" && !isVueHtml) { const shouldParseAsHTML = (node) => { + /* istanbul ignore next */ if (!node) { return false; } @@ -99,6 +100,7 @@ function ngHtmlParser( const endOffset = endSourceSpan.start.offset; for (const error of result.errors) { const { offset } = error.span.start; + /* istanbul ignore next */ if (startOffset < offset && offset < endOffset) { errors = [error]; break; @@ -145,6 +147,7 @@ function ngHtmlParser( } else if (node instanceof Text) { node.type = "text"; } else { + /* istanbul ignore next */ throw new Error(`Unexpected node ${JSON.stringify(node)}`); } }; @@ -299,6 +302,7 @@ function _parse(text, options, parserOptions, shouldParseFrontMatter = true) { ); const firstText = subAst.children[0]; if (firstText.length === offset) { + /* istanbul ignore next */ subAst.children.shift(); } else { firstText.sourceSpan = new ParseSourceSpan( diff --git a/src/language-html/printer-html.js b/src/language-html/printer-html.js index c4c8e74e4..fc8e99a13 100644 --- a/src/language-html/printer-html.js +++ b/src/language-html/printer-html.js @@ -78,21 +78,11 @@ function embed(path, print, textToDoc, options) { return; } - let doc; - try { - doc = textToDoc( - htmlTrimPreserveIndentation(getNodeContent(node, options)), - { parser }, - { stripTrailingHardline: true } - ); - } catch (_) { - return; - } - - // `textToDoc` don't throw on `production` mode - if (!doc) { - return; - } + const doc = textToDoc( + htmlTrimPreserveIndentation(getNodeContent(node, options)), + { parser }, + { stripTrailingHardline: true } + ); return concat([ printOpeningTagPrefix(node, options), @@ -446,10 +436,8 @@ function genericPrint(path, options, print) { ]), ]); } - case "yaml": - case "toml": - return concat(replaceEndOfLineWith(node.raw, literalline)); default: + /* istanbul ignore next */ throw new Error(`Unexpected node type ${node.type}`); } } @@ -957,6 +945,7 @@ function printOpeningTagEndMarker(node) { function printClosingTagStartMarker(node, options) { assert(!node.isSelfClosing); + /* istanbul ignore next */ if (shouldNotPrintClosingTag(node, options)) { return ""; } diff --git a/src/language-html/utils.js b/src/language-html/utils.js index 19ae1285f..6424395ec 100644 --- a/src/language-html/utils.js +++ b/src/language-html/utils.js @@ -92,10 +92,12 @@ function shouldPreserveContent(node, options) { } function hasPrettierIgnore(node) { + /* istanbul ignore next */ if (node.type === "attribute") { return false; } + /* istanbul ignore next */ if (!node.parent) { return false; } @@ -429,8 +431,6 @@ function inferScriptParser(node, options) { getParserName(node.attrMap.lang, options) ); } - - return null; } function isBlockLikeCssDisplay(cssDisplay) { @@ -465,7 +465,7 @@ function isPreLikeNode(node) { return getNodeCssStyleWhiteSpace(node).startsWith("pre"); } -function countParents(path, predicate = () => true) { +function countParents(path, predicate) { let counter = 0; for (let i = path.stack.length - 1; i >= 0; i--) { const value = path.stack[i]; @@ -591,10 +591,6 @@ function dedentString(text, minIndent = getMinIndentation(text)) { .join("\n"); } -function identity(x) { - return x; -} - function shouldNotPrintClosingTag(node, options) { return ( !node.isSelfClosing && @@ -661,7 +657,6 @@ module.exports = { getNodeCssStyleWhiteSpace, getPrettierIgnoreAttributeCommentData, hasPrettierIgnore, - identity, inferScriptParser, isVueCustomBlock, isVueNonHtmlBlock, diff --git a/src/language-js/clean.js b/src/language-js/clean.js index ed818fa3f..94f2dd47c 100644 --- a/src/language-js/clean.js +++ b/src/language-js/clean.js @@ -54,38 +54,6 @@ function clean(ast, newObj, parent) { return null; } - // (TypeScript) Ignore `static` in `constructor(static p) {}` - // and `export` in `constructor(export p) {}` - if ( - ast.type === "TSParameterProperty" && - ast.accessibility === null && - !ast.readonly - ) { - return { - type: "Identifier", - name: ast.parameter.name, - typeAnnotation: newObj.parameter.typeAnnotation, - decorators: newObj.decorators, - }; - } - - // (TypeScript) ignore empty `specifiers` array - if ( - ast.type === "TSNamespaceExportDeclaration" && - ast.specifiers && - ast.specifiers.length === 0 - ) { - delete newObj.specifiers; - } - - // We convert
to
- if (ast.type === "JSXOpeningElement") { - delete newObj.selfClosing; - } - if (ast.type === "JSXElement") { - delete newObj.closingElement; - } - // We change {'key': value} into {key: value}. // And {key: value} into {'key': value}. // Also for (some) number keys. diff --git a/src/language-js/parser-typescript.js b/src/language-js/parser-typescript.js index b995f4f55..ca5ede2bb 100644 --- a/src/language-js/parser-typescript.js +++ b/src/language-js/parser-typescript.js @@ -19,6 +19,7 @@ function parse(text, parsers, opts) { // suppose our guess is correct const e = firstError; + /* istanbul ignore next */ if (typeof e.lineNumber === "undefined") { throw e; } diff --git a/src/language-js/print/member-chain.js b/src/language-js/print/member-chain.js index 15734d116..fa2cd2535 100644 --- a/src/language-js/print/member-chain.js +++ b/src/language-js/print/member-chain.js @@ -323,6 +323,7 @@ function printMemberChain(path, options, print) { } function printIndentedGroup(groups) { + /* istanbul ignore next */ if (groups.length === 0) { return ""; } diff --git a/src/language-js/printer-estree.js b/src/language-js/printer-estree.js index 2e728379e..66f2e0f34 100644 --- a/src/language-js/printer-estree.js +++ b/src/language-js/printer-estree.js @@ -3999,6 +3999,7 @@ function shouldPrintParamsWithoutParens(path, options) { } // Fallback default; should be unreachable + /* istanbul ignore next */ return false; } @@ -4757,6 +4758,7 @@ function printJSXElement(path, options, print) { function maybeWrapJSXElementInParens(path, elem, options) { const parent = path.getParentNode(); + /* istanbul ignore next */ if (!parent) { return elem; } @@ -5285,6 +5287,7 @@ function printComment(commentPath, options) { .slice(options.locStart(comment), options.locEnd(comment)) .trimEnd(); default: + /* istanbul ignore next */ throw new Error("Not a comment: " + JSON.stringify(comment)); } } diff --git a/src/language-js/utils.js b/src/language-js/utils.js index cc45f3749..793f2c1c9 100644 --- a/src/language-js/utils.js +++ b/src/language-js/utils.js @@ -868,7 +868,7 @@ function isLastStatement(path) { const body = (parent.body || parent.consequent).filter( (stmt) => stmt.type !== "EmptyStatement" ); - return body && body[body.length - 1] === node; + return body[body.length - 1] === node; } /** diff --git a/src/language-markdown/index.js b/src/language-markdown/index.js index 8d4318b06..318a691a4 100644 --- a/src/language-markdown/index.js +++ b/src/language-markdown/index.js @@ -27,6 +27,7 @@ const printers = { }; const parsers = { + /* istanbul ignore next */ get remark() { return require("./parser-markdown").parsers.remark; }, diff --git a/src/language-markdown/mdx.js b/src/language-markdown/mdx.js index d73610de9..9a7ca3101 100644 --- a/src/language-markdown/mdx.js +++ b/src/language-markdown/mdx.js @@ -45,6 +45,7 @@ const tokenizeEsSyntax = (eat, value) => { } }; +/* istanbul ignore next */ tokenizeEsSyntax.locator = (value /*, fromIndex*/) => { return isExport(value) || isImport(value) ? -1 : 1; }; diff --git a/src/language-markdown/printer-markdown.js b/src/language-markdown/printer-markdown.js index dfc6171e1..c338ce9c5 100644 --- a/src/language-markdown/printer-markdown.js +++ b/src/language-markdown/printer-markdown.js @@ -258,12 +258,6 @@ function genericPrint(path, options, print) { style, ]); } - case "yaml": - case "toml": - return options.originalText.slice( - node.position.start.offset, - node.position.end.offset - ); case "html": { const parentNode = path.getParentNode(); const value = @@ -385,6 +379,9 @@ function genericPrint(path, options, print) { ]) ); } + // `footnote` requires `.use(footnotes, {inlineNotes: true})`, we are not using this option + // https://github.com/remarkjs/remark-footnotes#optionsinlinenotes + /* istanbul ignore next */ case "footnote": return concat(["[^", printChildren(path, options, print), "]"]); case "footnoteReference": @@ -463,6 +460,7 @@ function genericPrint(path, options, print) { case "tableRow": // handled in "table" case "listItem": // handled in "list" default: + /* istanbul ignore next */ throw new Error(`Unknown markdown type ${JSON.stringify(node.type)}`); } } @@ -768,6 +766,8 @@ function printChildren(path, options, print, events) { if (!shouldNotPrePrintHardline(childNode, data)) { parts.push(hardline); + // Can't find a case to pass `shouldPrePrintTripleHardline` + /* istanbul ignore next */ if (lastChildNode && TRAILING_HARDLINE_NODES.has(lastChildNode.type)) { if (shouldPrePrintTripleHardline(childNode, data)) { parts.push(hardline); diff --git a/src/language-yaml/parser-yaml.js b/src/language-yaml/parser-yaml.js index e7d8c3530..5b83bd74a 100644 --- a/src/language-yaml/parser-yaml.js +++ b/src/language-yaml/parser-yaml.js @@ -17,10 +17,12 @@ function parse(text) { return root; } catch (error) { - // istanbul ignore next - throw error && error.position - ? createError(error.message, error.position) - : error; + if (error && error.position) { + throw createError(error.message, error.position); + } + + /* istanbul ignore next */ + throw error; } } @@ -28,8 +30,13 @@ const parser = { astFormat: "yaml", parse, hasPragma, - locStart: (node) => node.position.start.offset, - locEnd: (node) => node.position.end.offset, + locStart(node) { + return node.position.start.offset; + }, + /* istanbul ignore next */ + locEnd(node) { + return node.position.end.offset; + }, }; module.exports = { diff --git a/src/language-yaml/printer-yaml.js b/src/language-yaml/printer-yaml.js index 5b899ca7c..42a51a471 100644 --- a/src/language-yaml/printer-yaml.js +++ b/src/language-yaml/printer-yaml.js @@ -551,6 +551,7 @@ function align(n, doc) { } function isInlineNode(node) { + /* istanbul ignore next */ if (!node) { return true; } @@ -569,6 +570,7 @@ function isInlineNode(node) { } function isSingleLineNode(node) { + /* istanbul ignore next */ if (!node) { return true; } diff --git a/src/language-yaml/utils.js b/src/language-yaml/utils.js index dd57e4dbb..d645938a8 100644 --- a/src/language-yaml/utils.js +++ b/src/language-yaml/utils.js @@ -165,6 +165,7 @@ function splitWithSingleSpace(text) { let lastPart; for (const part of text.split(/( +)/g)) { + /* istanbul ignore else */ if (part !== " ") { if (lastPart === " ") { parts.push(part); @@ -178,6 +179,7 @@ function splitWithSingleSpace(text) { lastPart = part; } + /* istanbul ignore next */ if (lastPart === " ") { parts.push((parts.pop() || "") + " "); } diff --git a/src/main/comments.js b/src/main/comments.js index 2fc7962ab..acb834360 100644 --- a/src/main/comments.js +++ b/src/main/comments.js @@ -381,6 +381,7 @@ function findExpressionIndexForComment(quasis, comment, options) { function printLeadingComment(commentPath, options) { const comment = commentPath.getValue(); const contents = printComment(commentPath, options); + /* istanbul ignore next */ if (!contents) { return ""; } @@ -407,6 +408,7 @@ function printLeadingComment(commentPath, options) { function printTrailingComment(commentPath, options) { const comment = commentPath.getValue(); const contents = printComment(commentPath, options); + /* istanbul ignore next */ if (!contents) { return ""; } @@ -502,6 +504,7 @@ function printComments(path, print, options, needsSemi) { if (leading) { const contents = printLeadingComment(commentPath, options); + /* istanbul ignore next */ if (!contents) { return; } diff --git a/src/main/core.js b/src/main/core.js index 35150d7e3..f7cb272f7 100644 --- a/src/main/core.js +++ b/src/main/core.js @@ -274,6 +274,7 @@ function format(text, opts) { if (!hasCursor) { opts.cursorOffset = -1; } + /* istanbul ignore next */ if (opts.rangeStart < 0) { opts.rangeStart = 0; } diff --git a/src/main/multiparser.js b/src/main/multiparser.js index 023f9843c..26cc5c3ce 100644 --- a/src/main/multiparser.js +++ b/src/main/multiparser.js @@ -71,6 +71,7 @@ function textToDoc( return stripTrailingHardline(doc, true); } + /* istanbul ignore next */ return doc; } diff --git a/src/main/options-normalizer.js b/src/main/options-normalizer.js index 43b63fd95..b93ddce28 100644 --- a/src/main/options-normalizer.js +++ b/src/main/options-normalizer.js @@ -161,6 +161,7 @@ function optionInfoToSchema(optionInfo, { isCLI, optionInfos }) { SchemaConstructor = vnopts.StringSchema; break; default: + /* istanbul ignore next */ throw new Error(`Unexpected type ${optionInfo.type}`); } @@ -174,6 +175,7 @@ function optionInfoToSchema(optionInfo, { isCLI, optionInfos }) { }; } + /* istanbul ignore next */ if (optionInfo.redirect) { handlers.redirect = (value) => !value @@ -186,6 +188,7 @@ function optionInfoToSchema(optionInfo, { isCLI, optionInfos }) { }; } + /* istanbul ignore next */ if (optionInfo.deprecated) { handlers.deprecated = true; } diff --git a/src/main/options.js b/src/main/options.js index 8b9bd6434..386e9eb99 100644 --- a/src/main/options.js +++ b/src/main/options.js @@ -105,12 +105,16 @@ function normalize(options, opts) { function getPlugin(options) { const { astFormat } = options; + // TODO: test this with plugins + /* istanbul ignore next */ if (!astFormat) { throw new Error("getPlugin() requires astFormat to be set"); } const printerPlugin = options.plugins.find( (plugin) => plugin.printers && plugin.printers[astFormat] ); + // TODO: test this with plugins + /* istanbul ignore next */ if (!printerPlugin) { throw new Error(`Couldn't find plugin for AST format "${astFormat}"`); } @@ -119,6 +123,7 @@ function getPlugin(options) { } function getInterpreter(filepath) { + /* istanbul ignore next */ if (typeof filepath !== "string") { return ""; } @@ -150,6 +155,7 @@ function getInterpreter(filepath) { } catch (err) { // There are some weird cases where paths are missing, causing Jest // failures. It's unclear what these correspond to in the real world. + /* istanbul ignore next */ return ""; } finally { try { diff --git a/src/main/parser.js b/src/main/parser.js index 2347fc9c8..c3928fd49 100644 --- a/src/main/parser.js +++ b/src/main/parser.js @@ -13,6 +13,8 @@ const ownDescriptor = Object.getOwnPropertyDescriptor; function getParsers(options) { const parsers = {}; for (const plugin of options.plugins) { + // TODO: test this with plugins + /* istanbul ignore next */ if (!plugin.parsers) { continue; } @@ -48,18 +50,18 @@ function resolveParser(opts, parsers) { throw new ConfigError( `Couldn't resolve parser "${opts.parser}". Parsers must be explicitly added to the standalone bundle.` ); - } else { - try { - return { - parse: eval("require")(path.resolve(process.cwd(), opts.parser)), - astFormat: "estree", - locStart, - locEnd, - }; - } catch (err) { - /* istanbul ignore next */ - throw new ConfigError(`Couldn't resolve parser "${opts.parser}"`); - } + } + + try { + return { + parse: eval("require")(path.resolve(process.cwd(), opts.parser)), + astFormat: "estree", + locStart, + locEnd, + }; + } catch (err) { + /* istanbul ignore next */ + throw new ConfigError(`Couldn't resolve parser "${opts.parser}"`); } } } diff --git a/src/main/range-util.js b/src/main/range-util.js index a572a3c93..cf041748b 100644 --- a/src/main/range-util.js +++ b/src/main/range-util.js @@ -109,6 +109,7 @@ const graphqlSourceElements = new Set([ "ScalarTypeDefinition", ]); function isSourceElement(opts, node) { + /* istanbul ignore next */ if (node == null) { return false; } diff --git a/src/utils/front-matter.js b/src/utils/front-matter.js index 965977c57..bd1b83f5e 100644 --- a/src/utils/front-matter.js +++ b/src/utils/front-matter.js @@ -2,8 +2,7 @@ const escape = require("escape-string-regexp"); const { - builders: { hardline, literalline, concat, markAsRoot }, - utils: { mapDoc }, + builders: { hardline, concat, markAsRoot }, } = require("../document"); const DELIMITER_MAP = { @@ -46,9 +45,7 @@ function print(node, textToDoc) { if (node.lang === "yaml") { const value = node.value.trim(); const doc = value - ? replaceNewlinesWithLiterallines( - textToDoc(value, { parser: "yaml" }, { stripTrailingHardline: true }) - ) + ? textToDoc(value, { parser: "yaml" }, { stripTrailingHardline: true }) : ""; return markAsRoot( concat(["---", hardline, doc, doc ? hardline : "", "---"]) @@ -56,16 +53,4 @@ function print(node, textToDoc) { } } -function replaceNewlinesWithLiterallines(doc) { - return mapDoc(doc, (currentDoc) => - typeof currentDoc === "string" && currentDoc.includes("\n") - ? concat( - currentDoc - .split(/(\n)/g) - .map((v, i) => (i % 2 === 0 ? v : literalline)) - ) - : currentDoc - ); -} - module.exports = { parse, print }; diff --git a/src/utils/line-column-to-index.js b/src/utils/line-column-to-index.js index 1cb72bbad..09911a5b2 100644 --- a/src/utils/line-column-to-index.js +++ b/src/utils/line-column-to-index.js @@ -5,9 +5,6 @@ module.exports = function (lineColumn, text) { let index = 0; for (let i = 0; i < lineColumn.line - 1; ++i) { index = text.indexOf("\n", index) + 1; - if (index === -1) { - return -1; - } } return index + lineColumn.column; }; diff --git a/tests/graphql/type-extension-definition/__snapshots__/jsfmt.spec.js.snap b/tests/graphql/type-extension-definition/__snapshots__/jsfmt.spec.js.snap new file mode 100644 index 000000000..aa69d1311 --- /dev/null +++ b/tests/graphql/type-extension-definition/__snapshots__/jsfmt.spec.js.snap @@ -0,0 +1,29 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-extendsion-syntax.graphql format 1`] = ` +====================================options===================================== +parsers: ["graphql"] +printWidth: 80 + | printWidth +=====================================input====================================== +type User { + name: String + birthday: Int +} + +extend type User { + age: Int +} + +=====================================output===================================== +type User { + name: String + birthday: Int +} + +extend type User { + age: Int +} + +================================================================================ +`; diff --git a/tests/graphql/type-extension-definition/jsfmt.spec.js b/tests/graphql/type-extension-definition/jsfmt.spec.js new file mode 100644 index 000000000..4612e6ac5 --- /dev/null +++ b/tests/graphql/type-extension-definition/jsfmt.spec.js @@ -0,0 +1 @@ +run_spec(__dirname, ["graphql"]); diff --git a/tests/graphql/type-extension-definition/type-extendsion-syntax.graphql b/tests/graphql/type-extension-definition/type-extendsion-syntax.graphql new file mode 100644 index 000000000..4b67be477 --- /dev/null +++ b/tests/graphql/type-extension-definition/type-extendsion-syntax.graphql @@ -0,0 +1,8 @@ +type User { + name: String + birthday: Int +} + +extend type User { + age: Int +} diff --git a/tests/html/cdata/__snapshots__/jsfmt.spec.js.snap b/tests/html/cdata/__snapshots__/jsfmt.spec.js.snap index 53980c95f..2ac87c24d 100644 --- a/tests/html/cdata/__snapshots__/jsfmt.spec.js.snap +++ b/tests/html/cdata/__snapshots__/jsfmt.spec.js.snap @@ -8,8 +8,17 @@ printWidth: 80 =====================================input====================================== John Smith]]> + a +
+ =====================================output===================================== John Smith]]> + a +
+
+ ================================================================================ `; diff --git a/tests/html/cdata/example.html b/tests/html/cdata/example.html index e62ba2a30..df7ff8e62 100644 --- a/tests/html/cdata/example.html +++ b/tests/html/cdata/example.html @@ -1 +1,4 @@ John Smith]]> + + a +
diff --git a/tests/html/srcset/__snapshots__/jsfmt.spec.js.snap b/tests/html/srcset/__snapshots__/jsfmt.spec.js.snap new file mode 100644 index 000000000..502b9318a --- /dev/null +++ b/tests/html/srcset/__snapshots__/jsfmt.spec.js.snap @@ -0,0 +1,41 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`invalid.html format 1`] = ` +====================================options===================================== +parsers: ["html"] +printWidth: 80 + | printWidth +=====================================input====================================== + + + + +=====================================output===================================== + + + + +================================================================================ +`; diff --git a/tests/html/srcset/invalid.html b/tests/html/srcset/invalid.html new file mode 100644 index 000000000..7978c5469 --- /dev/null +++ b/tests/html/srcset/invalid.html @@ -0,0 +1,12 @@ + + + diff --git a/tests/html/srcset/jsfmt.spec.js b/tests/html/srcset/jsfmt.spec.js new file mode 100644 index 000000000..53763df9b --- /dev/null +++ b/tests/html/srcset/jsfmt.spec.js @@ -0,0 +1 @@ +run_spec(__dirname, ["html"]); diff --git a/tests/js/bom/__snapshots__/jsfmt.spec.js.snap b/tests/js/bom/__snapshots__/jsfmt.spec.js.snap index 61ed38cd0..a3dfa748b 100644 --- a/tests/js/bom/__snapshots__/jsfmt.spec.js.snap +++ b/tests/js/bom/__snapshots__/jsfmt.spec.js.snap @@ -16,6 +16,32 @@ printWidth: 80 ================================================================================ `; +exports[`snippet: cursor-and-range.js format 1`] = ` +====================================options===================================== +parsers: ["babel"] +printWidth: 80 + | | printWidth +=====================================input====================================== + 1 |  + 2 | +> 3 | class a { + | ^^^^ +> 4 | b( <|> ) {} + | ^^^^^^^^^^^^^^ + 5 | } + 6 | + 7 | let x +=====================================output===================================== + + +class a { + b(<|>) {} +} + +let x +================================================================================ +`; + exports[`snippet: range-1.js format 1`] = ` ====================================options===================================== parsers: ["babel"] diff --git a/tests/js/eol/__snapshots__/jsfmt.spec.js.snap b/tests/js/eol/__snapshots__/jsfmt.spec.js.snap index 4e93e2e43..7f31a623f 100644 --- a/tests/js/eol/__snapshots__/jsfmt.spec.js.snap +++ b/tests/js/eol/__snapshots__/jsfmt.spec.js.snap @@ -69,6 +69,115 @@ printWidth: 80 ================================================================================ `; +exports[`cursor-and-range.js - {"endOfLine":"auto"} format 1`] = ` +====================================options===================================== +endOfLine: "auto" +parsers: ["babel"] +printWidth: 80 + | | printWidth +=====================================input====================================== + 1 | + 2 | +> 3 | class a { + | ^^^^ +> 4 | b( <|> ) {} + | ^^^^^^^^^^^^^^ + 5 | } + 6 | + 7 | let x +=====================================output===================================== +** The EOL of output might not real when \`TEST_CRLF\` ** + + +class a { + b(<|>) {} +} + +let x +================================================================================ +`; + +exports[`cursor-and-range.js - {"endOfLine":"cr"} format 1`] = ` +====================================options===================================== +endOfLine: "cr" +parsers: ["babel"] +printWidth: 80 + | | printWidth +=====================================input====================================== + 1 | + 2 | +> 3 | class a { + | ^^^^ +> 4 | b( <|> ) {} + | ^^^^^^^^^^^^^^ + 5 | } + 6 | + 7 | let x +=====================================output===================================== + + +class a { + b(<|>) {} +} + +let x +================================================================================ +`; + +exports[`cursor-and-range.js - {"endOfLine":"crlf"} format 1`] = ` +====================================options===================================== +endOfLine: "crlf" +parsers: ["babel"] +printWidth: 80 + | | printWidth +=====================================input====================================== + 1 | + 2 | +> 3 | class a { + | ^^^^ +> 4 | b( <|> ) {} + | ^^^^^^^^^^^^^^ + 5 | } + 6 | + 7 | let x +=====================================output===================================== + + +class a { + b(<|>) {} +} + +let x +================================================================================ +`; + +exports[`cursor-and-range.js - {"endOfLine":"lf"} format 1`] = ` +====================================options===================================== +endOfLine: "lf" +parsers: ["babel"] +printWidth: 80 + | | printWidth +=====================================input====================================== + 1 | + 2 | +> 3 | class a { + | ^^^^ +> 4 | b( <|> ) {} + | ^^^^^^^^^^^^^^ + 5 | } + 6 | + 7 | let x +=====================================output===================================== + + +class a { + b(<|>) {} +} + +let x +================================================================================ +`; + exports[`range-1.js - {"endOfLine":"auto"} format 1`] = ` ====================================options===================================== endOfLine: "auto" diff --git a/tests/js/eol/cursor-and-range.js b/tests/js/eol/cursor-and-range.js new file mode 100644 index 000000000..813dbfdef --- /dev/null +++ b/tests/js/eol/cursor-and-range.js @@ -0,0 +1,7 @@ + + +class <<>> a { + b( <|> ) {}<<>> +} + +let x \ No newline at end of file diff --git a/tests/js/range/__snapshots__/jsfmt.spec.js.snap b/tests/js/range/__snapshots__/jsfmt.spec.js.snap index a842fb8f2..99e03bb44 100644 --- a/tests/js/range/__snapshots__/jsfmt.spec.js.snap +++ b/tests/js/range/__snapshots__/jsfmt.spec.js.snap @@ -1,5 +1,29 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`array.js format 1`] = ` +====================================options===================================== +parsers: ["babel", "flow", "typescript"] +printWidth: 80 + | | printWidth +=====================================input====================================== + 1 | a = [ + 2 | , +> 3 | ,,,, + | ^^^^ +> 4 | + | ^ +> 5 | , + | ^ +> 6 | + | ^ + 7 | , + 8 | a, + 9 | ] +=====================================output===================================== +a = [, , , , , , , a]; +================================================================================ +`; + exports[`class-declaration.js format 1`] = ` ====================================options===================================== parsers: ["babel", "flow", "typescript"] diff --git a/tests/js/range/array.js b/tests/js/range/array.js new file mode 100644 index 000000000..4cf65b0c9 --- /dev/null +++ b/tests/js/range/array.js @@ -0,0 +1,9 @@ +a = [ +, +<<>>,,,, + +, +<<>> +, +a, +] \ No newline at end of file diff --git a/tests/markdown/footnote/__snapshots__/jsfmt.spec.js.snap b/tests/markdown/footnote/__snapshots__/jsfmt.spec.js.snap index abfe09270..1812a7a44 100644 --- a/tests/markdown/footnote/__snapshots__/jsfmt.spec.js.snap +++ b/tests/markdown/footnote/__snapshots__/jsfmt.spec.js.snap @@ -1,5 +1,20 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`footnote.md - {"proseWrap":"always"} format 1`] = ` +====================================options===================================== +parsers: ["markdown"] +printWidth: 80 +proseWrap: "always" + | printWidth +=====================================input====================================== +^[inline] + +=====================================output===================================== +^[inline] + +================================================================================ +`; + exports[`simple.md - {"proseWrap":"always"} format 1`] = ` ====================================options===================================== parsers: ["markdown"] diff --git a/tests/markdown/footnote/footnote.md b/tests/markdown/footnote/footnote.md new file mode 100644 index 000000000..324549a6e --- /dev/null +++ b/tests/markdown/footnote/footnote.md @@ -0,0 +1 @@ +^[inline] diff --git a/tests/misc/embedded_language_formatting/in-html/__snapshots__/jsfmt.spec.js.snap b/tests/misc/embedded_language_formatting/in-html/__snapshots__/jsfmt.spec.js.snap index b10014a63..9c2ce1397 100644 --- a/tests/misc/embedded_language_formatting/in-html/__snapshots__/jsfmt.spec.js.snap +++ b/tests/misc/embedded_language_formatting/in-html/__snapshots__/jsfmt.spec.js.snap @@ -1,5 +1,121 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`front-matter-toml.html - {"embeddedLanguageFormatting":"off"} format 1`] = ` +====================================options===================================== +embeddedLanguageFormatting: "off" +parsers: ["html"] +printWidth: 80 + | printWidth +=====================================input====================================== ++++ + +title: Hello +slug: home + ++++ + +

+ Hello world!

+ +=====================================output===================================== ++++ + +title: Hello +slug: home + ++++ + +

Hello world!

+ +================================================================================ +`; + +exports[`front-matter-toml.html format 1`] = ` +====================================options===================================== +parsers: ["html"] +printWidth: 80 + | printWidth +=====================================input====================================== ++++ + +title: Hello +slug: home + ++++ + +

+ Hello world!

+ +=====================================output===================================== ++++ + +title: Hello +slug: home + ++++ + +

Hello world!

+ +================================================================================ +`; + +exports[`front-matter-yaml.html - {"embeddedLanguageFormatting":"off"} format 1`] = ` +====================================options===================================== +embeddedLanguageFormatting: "off" +parsers: ["html"] +printWidth: 80 + | printWidth +=====================================input====================================== +---yaml + +title: Hello +slug: home + +--- + +

+ Hello world!

+ +=====================================output===================================== +---yaml + +title: Hello +slug: home + +--- + +

Hello world!

+ +================================================================================ +`; + +exports[`front-matter-yaml.html format 1`] = ` +====================================options===================================== +parsers: ["html"] +printWidth: 80 + | printWidth +=====================================input====================================== +---yaml + +title: Hello +slug: home + +--- + +

+ Hello world!

+ +=====================================output===================================== +--- +title: Hello +slug: home +--- + +

Hello world!

+ +================================================================================ +`; + exports[`test.html - {"embeddedLanguageFormatting":"off"} format 1`] = ` ====================================options===================================== embeddedLanguageFormatting: "off" diff --git a/tests/misc/embedded_language_formatting/in-html/front-matter-toml.html b/tests/misc/embedded_language_formatting/in-html/front-matter-toml.html new file mode 100644 index 000000000..d0dfe44bb --- /dev/null +++ b/tests/misc/embedded_language_formatting/in-html/front-matter-toml.html @@ -0,0 +1,9 @@ ++++ + +title: Hello +slug: home + ++++ + +

+ Hello world!

diff --git a/tests/misc/embedded_language_formatting/in-html/front-matter-yaml.html b/tests/misc/embedded_language_formatting/in-html/front-matter-yaml.html new file mode 100644 index 000000000..0698ae247 --- /dev/null +++ b/tests/misc/embedded_language_formatting/in-html/front-matter-yaml.html @@ -0,0 +1,9 @@ +---yaml + +title: Hello +slug: home + +--- + +

+ Hello world!

diff --git a/tests/misc/errors/handlebars/__snapshots__/jsfmt.spec.js.snap b/tests/misc/errors/handlebars/__snapshots__/jsfmt.spec.js.snap new file mode 100644 index 000000000..5b21fc6e6 --- /dev/null +++ b/tests/misc/errors/handlebars/__snapshots__/jsfmt.spec.js.snap @@ -0,0 +1,11 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`invalid.hbs error test 1`] = ` +"Parse error on line 2: +x, {{@name} +--------------^ +Expecting 'CLOSE_RAW_BLOCK', 'CLOSE', 'CLOSE_UNESCAPED', 'OPEN_SEXPR', 'CLOSE_SEXPR', 'ID', 'OPEN_BLOCK_PARAMS', 'STRING', 'NUMBER', 'BOOLEAN', 'UNDEFINED', 'NULL', 'DATA', 'SEP', got 'INVALID' (2:0) + 1 | +> 2 | x, {{@name} + 3 | " +`; diff --git a/tests/misc/errors/handlebars/invalid.hbs b/tests/misc/errors/handlebars/invalid.hbs new file mode 100644 index 000000000..76674d8e2 --- /dev/null +++ b/tests/misc/errors/handlebars/invalid.hbs @@ -0,0 +1,2 @@ + +x, {{@name} diff --git a/tests/misc/errors/handlebars/jsfmt.spec.js b/tests/misc/errors/handlebars/jsfmt.spec.js new file mode 100644 index 000000000..da9b88409 --- /dev/null +++ b/tests/misc/errors/handlebars/jsfmt.spec.js @@ -0,0 +1 @@ +run_spec(__dirname, ["glimmer"]); diff --git a/tests/misc/errors/less/__snapshots__/jsfmt.spec.js.snap b/tests/misc/errors/less/__snapshots__/jsfmt.spec.js.snap index 73f60c218..e113e898d 100644 --- a/tests/misc/errors/less/__snapshots__/jsfmt.spec.js.snap +++ b/tests/misc/errors/less/__snapshots__/jsfmt.spec.js.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`inline-comment.js error test 1`] = ` +exports[`inline-comment.less error test 1`] = ` "(postcss) CssSyntaxError Unknown word (5:4) 3 | a{ 4 | prop @@ -10,3 +10,21 @@ exports[`inline-comment.js error test 1`] = ` 7 | value; 8 | }" `; + +exports[`open-double-quote.less error test 1`] = ` +"(postcss) CssSyntaxError Unclosed string (2:17) + 1 | a { +> 2 | background: url(\\" + | ^ + 3 | } + 4 | " +`; + +exports[`open-sigle-quote.less error test 1`] = ` +"(postcss) CssSyntaxError Unclosed string (2:17) + 1 | a { +> 2 | background: url(' + | ^ + 3 | } + 4 | " +`; diff --git a/tests/misc/errors/less/inline-comment.js b/tests/misc/errors/less/inline-comment.less similarity index 100% rename from tests/misc/errors/less/inline-comment.js rename to tests/misc/errors/less/inline-comment.less diff --git a/tests/misc/errors/less/open-double-quote.less b/tests/misc/errors/less/open-double-quote.less new file mode 100644 index 000000000..b71d3cdac --- /dev/null +++ b/tests/misc/errors/less/open-double-quote.less @@ -0,0 +1,3 @@ +a { +background: url(" +} diff --git a/tests/misc/errors/less/open-sigle-quote.less b/tests/misc/errors/less/open-sigle-quote.less new file mode 100644 index 000000000..a4a4e3c33 --- /dev/null +++ b/tests/misc/errors/less/open-sigle-quote.less @@ -0,0 +1,3 @@ +a { +background: url(' +} diff --git a/tests/vue/v-for/__snapshots__/jsfmt.spec.js.snap b/tests/vue/v-for/__snapshots__/jsfmt.spec.js.snap new file mode 100644 index 000000000..41fbb87e9 --- /dev/null +++ b/tests/vue/v-for/__snapshots__/jsfmt.spec.js.snap @@ -0,0 +1,21 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`invalid.vue format 1`] = ` +====================================options===================================== +parsers: ["vue"] +printWidth: 80 + | printWidth +=====================================input====================================== + + +=====================================output===================================== + + +================================================================================ +`; diff --git a/tests/vue/v-for/invalid.vue b/tests/vue/v-for/invalid.vue new file mode 100644 index 000000000..ff40322d9 --- /dev/null +++ b/tests/vue/v-for/invalid.vue @@ -0,0 +1,5 @@ + diff --git a/tests/vue/v-for/jsfmt.spec.js b/tests/vue/v-for/jsfmt.spec.js new file mode 100644 index 000000000..2fd7eede9 --- /dev/null +++ b/tests/vue/v-for/jsfmt.spec.js @@ -0,0 +1 @@ +run_spec(__dirname, ["vue"]); diff --git a/tests/vue/vue/__snapshots__/jsfmt.spec.js.snap b/tests/vue/vue/__snapshots__/jsfmt.spec.js.snap index 0df004d69..c75364851 100644 --- a/tests/vue/vue/__snapshots__/jsfmt.spec.js.snap +++ b/tests/vue/vue/__snapshots__/jsfmt.spec.js.snap @@ -41,6 +41,10 @@ semi: false " @click="doSomething()" @click="doSomething;" + @click="a.b;" + @click="a[1];" + @click="a['b'];" + @click="a[null];" #default="{foo:{bar:{baz}}}" >
@@ -104,6 +108,10 @@ semi: false " @click="doSomething()" @click="doSomething;" + @click="a.b;" + @click="a[1];" + @click="a['b'];" + @click="a[null]" #default="{ foo: { bar: { baz } } }" > @@ -152,6 +160,10 @@ trailingComma: "none" " @click="doSomething()" @click="doSomething;" + @click="a.b;" + @click="a[1];" + @click="a['b'];" + @click="a[null];" #default="{foo:{bar:{baz}}}" > @@ -215,6 +227,10 @@ trailingComma: "none" " @click="doSomething()" @click="doSomething;" + @click="a.b;" + @click="a[1];" + @click="a['b'];" + @click="a[null]" #default="{ foo: { bar: { baz } } }" > @@ -262,6 +278,10 @@ printWidth: 80 " @click="doSomething()" @click="doSomething;" + @click="a.b;" + @click="a[1];" + @click="a['b'];" + @click="a[null];" #default="{foo:{bar:{baz}}}" > @@ -325,6 +345,10 @@ printWidth: 80 " @click="doSomething()" @click="doSomething;" + @click="a.b;" + @click="a[1];" + @click="a['b'];" + @click="a[null]" #default="{ foo: { bar: { baz } } }" > diff --git a/tests/vue/vue/attributes.vue b/tests/vue/vue/attributes.vue index 0d2e42fc3..fe1585cf4 100644 --- a/tests/vue/vue/attributes.vue +++ b/tests/vue/vue/attributes.vue @@ -32,6 +32,10 @@ " @click="doSomething()" @click="doSomething;" + @click="a.b;" + @click="a[1];" + @click="a['b'];" + @click="a[null];" #default="{foo:{bar:{baz}}}" > diff --git a/tests_integration/__tests__/__snapshots__/config-invalid.js.snap b/tests_integration/__tests__/__snapshots__/config-invalid.js.snap index f6713ed29..89b2714f1 100644 --- a/tests_integration/__tests__/__snapshots__/config-invalid.js.snap +++ b/tests_integration/__tests__/__snapshots__/config-invalid.js.snap @@ -38,8 +38,12 @@ exports[`throw error for unsupported extension (write) 1`] = `Array []`; exports[`throw error with invalid config format (stdout) 1`] = `""`; +exports[`throw error with invalid config format (stdout) 2`] = `""`; + exports[`throw error with invalid config format (write) 1`] = `Array []`; +exports[`throw error with invalid config format (write) 2`] = `Array []`; + exports[`throw error with invalid config option (int) (stderr) 1`] = ` "[error] Invalid tabWidth value. Expected an integer, but received 0.5. " diff --git a/tests_integration/__tests__/__snapshots__/debug-api.js.snap b/tests_integration/__tests__/__snapshots__/debug-api.js.snap new file mode 100644 index 000000000..455167804 --- /dev/null +++ b/tests_integration/__tests__/__snapshots__/debug-api.js.snap @@ -0,0 +1,16 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`API prettier.formatDoc 1`] = ` +"[ + group([ + \\"const\\", + \\" \\", + group([\\"foo\\", \\" =\\", group(indent([line, '\\"bar\\"']))]), + indent([]), + \\";\\", + ]), + hardline, + breakParent, +]; +" +`; diff --git a/tests_integration/__tests__/__snapshots__/file-info.js.snap b/tests_integration/__tests__/__snapshots__/file-info.js.snap index 8250b405a..7a3c7901c 100644 --- a/tests_integration/__tests__/__snapshots__/file-info.js.snap +++ b/tests_integration/__tests__/__snapshots__/file-info.js.snap @@ -135,3 +135,13 @@ exports[`file-info should try resolve config (stdout) 1`] = ` `; exports[`file-info should try resolve config (write) 1`] = `Array []`; + +exports[`non-exists ignore path (stderr) 1`] = `""`; + +exports[`non-exists ignore path (stdout) 1`] = ` +"{ \\"ignored\\": false, \\"inferredParser\\": \\"babel\\" } + +" +`; + +exports[`non-exists ignore path (write) 1`] = `Array []`; diff --git a/tests_integration/__tests__/__snapshots__/stdin-filepath.js.snap b/tests_integration/__tests__/__snapshots__/stdin-filepath.js.snap index 2f065a2b1..f27f5e90f 100644 --- a/tests_integration/__tests__/__snapshots__/stdin-filepath.js.snap +++ b/tests_integration/__tests__/__snapshots__/stdin-filepath.js.snap @@ -1,5 +1,27 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`apply editorconfig for stdin-filepath with a deep path (stderr) 1`] = `""`; + +exports[`apply editorconfig for stdin-filepath with a deep path (stderr) 2`] = `""`; + +exports[`apply editorconfig for stdin-filepath with a deep path (stdout) 1`] = ` +"function f() { + console.log(\\"should be indented with a tab\\") +} +" +`; + +exports[`apply editorconfig for stdin-filepath with a deep path (stdout) 2`] = ` +"function f() { + console.log(\\"should be indented with a tab\\") +} +" +`; + +exports[`apply editorconfig for stdin-filepath with a deep path (write) 1`] = `Array []`; + +exports[`apply editorconfig for stdin-filepath with a deep path (write) 2`] = `Array []`; + exports[`apply editorconfig for stdin-filepath with nonexistent directory (stderr) 1`] = `""`; exports[`apply editorconfig for stdin-filepath with nonexistent directory (stdout) 1`] = ` diff --git a/tests_integration/__tests__/config-invalid.js b/tests_integration/__tests__/config-invalid.js index f5054b8fb..c94fbe96e 100644 --- a/tests_integration/__tests__/config-invalid.js +++ b/tests_integration/__tests__/config-invalid.js @@ -22,6 +22,18 @@ describe("throw error with invalid config format", () => { }); }); +describe("throw error with invalid config format", () => { + runPrettier("cli/config/invalid", [ + "--config", + "type-error/.prettierrc", + ]).test({ + status: "non-zero", + stderr: expect.stringMatching( + "Config is only allowed to be an object, but received number in" + ), + }); +}); + describe("throw error with invalid config target (directory)", () => { runPrettier("cli/config/invalid", [ "--config", diff --git a/tests_integration/__tests__/config-resolution.js b/tests_integration/__tests__/config-resolution.js index bea830899..64f5761e4 100644 --- a/tests_integration/__tests__/config-resolution.js +++ b/tests_integration/__tests__/config-resolution.js @@ -249,6 +249,35 @@ test("API resolveConfig.sync overrides work with absolute paths", () => { }); }); +test("API resolveConfig.sync overrides excludeFiles", () => { + const notOverride = path.join( + __dirname, + "../cli/config/overrides-exclude-files/foo" + ); + expect(prettier.resolveConfig.sync(notOverride)).toMatchObject({ + singleQuote: true, + trailingComma: "all", + }); + + const singleQuote = path.join( + __dirname, + "../cli/config/overrides-exclude-files/single-quote.js" + ); + expect(prettier.resolveConfig.sync(singleQuote)).toMatchObject({ + singleQuote: true, + trailingComma: "es5", + }); + + const doubleQuote = path.join( + __dirname, + "../cli/config/overrides-exclude-files/double-quote.js" + ); + expect(prettier.resolveConfig.sync(doubleQuote)).toMatchObject({ + singleQuote: false, + trailingComma: "es5", + }); +}); + test("API resolveConfig removes $schema option", () => { const file = path.resolve( path.join(__dirname, "../cli/config/$schema/index.js") diff --git a/tests_integration/__tests__/debug-api.js b/tests_integration/__tests__/debug-api.js new file mode 100644 index 000000000..39858ef54 --- /dev/null +++ b/tests_integration/__tests__/debug-api.js @@ -0,0 +1,44 @@ +"use strict"; + +const { + parse, + formatAST, + formatDoc, + printToDoc, + printDocToString, +} = require("prettier/local").__debug; +const { outdent } = require("outdent"); + +const code = outdent` + const foo = 'bar' +`; +const formatted = 'const foo = "bar";\n'; +const options = { parser: "babel", originalText: code }; + +describe("API", () => { + const { ast } = parse(code, options); + test("prettier.parse", () => { + expect(Array.isArray(ast.program.body)).toBe(true); + }); + + const { formatted: formatResultFromAST } = formatAST(ast, options); + test("prettier.formatAST", () => { + expect(formatResultFromAST).toBe(formatted); + }); + + const doc = printToDoc(code, options); + test("prettier.printToDoc", () => { + expect(doc.type).toBe("concat"); + expect(Array.isArray(doc.parts)).toBe(true); + }); + + const formatResultFromDoc = formatDoc(doc, options); + test("prettier.formatDoc", () => { + expect(formatResultFromDoc).toMatchSnapshot(); + }); + + const { formatted: stringFromDoc } = printDocToString(doc, options); + test("prettier.printDocToString", () => { + expect(stringFromDoc).toBe(formatted); + }); +}); diff --git a/tests_integration/__tests__/file-info.js b/tests_integration/__tests__/file-info.js index 96e80a319..c7790167c 100644 --- a/tests_integration/__tests__/file-info.js +++ b/tests_integration/__tests__/file-info.js @@ -62,6 +62,16 @@ describe("extracts file-info with ignored=true for a file in a hand-picked .pret }); }); +describe("non-exists ignore path", () => { + runPrettier("cli/", [ + "--file-info", + "regular-module.js", + "--ignore-path=ignore-path/non-exists/.prettierignore", + ]).test({ + status: 0, + }); +}); + describe("extracts file-info for a file in not_node_modules", () => { runPrettier("cli/with-node-modules/", [ "--file-info", diff --git a/tests_integration/__tests__/invalid-ignore.js b/tests_integration/__tests__/invalid-ignore.js index 3900dc62f..12784a1c8 100644 --- a/tests_integration/__tests__/invalid-ignore.js +++ b/tests_integration/__tests__/invalid-ignore.js @@ -1,5 +1,7 @@ "use strict"; +const path = require("path"); +const prettier = require("prettier/local"); const runPrettier = require("../runPrettier"); expect.addSnapshotSerializer(require("../path-serializer")); @@ -8,4 +10,15 @@ describe("throw error with invalid ignore", () => { runPrettier("cli/invalid-ignore", ["something.js"]).test({ status: "non-zero", }); + + test("sync api", async () => { + await expect( + prettier.getFileInfo("something.js", { + ignorePath: path.join( + __dirname, + "../cli/invalid-ignore/.prettierignore" + ), + }) + ).rejects.toThrow(/EISDIR: illegal operation on a directory/); + }); }); diff --git a/tests_integration/__tests__/plugin-options-string.js b/tests_integration/__tests__/plugin-options-string.js index 1c7f07f21..96e3008fa 100644 --- a/tests_integration/__tests__/plugin-options-string.js +++ b/tests_integration/__tests__/plugin-options-string.js @@ -54,3 +54,18 @@ describe("external options from config file should work", () => { write: [], }); }); + +describe("Non exists plugin", () => { + runPrettier( + "plugins/options-string", + ["--plugin=--invalid--", "--stdin-filepath", "example.foo"], + { input: "hello-world" } + ).test({ + stdout: "", + stderr: expect.stringMatching( + /Cannot (?:resolve|find) module '--invalid--' from/ + ), + status: 1, + write: [], + }); +}); diff --git a/tests_integration/__tests__/resolve-config-file.js b/tests_integration/__tests__/resolve-config-file.js new file mode 100644 index 000000000..44e191a62 --- /dev/null +++ b/tests_integration/__tests__/resolve-config-file.js @@ -0,0 +1,15 @@ +"use strict"; + +const path = require("path"); + +const prettier = require("prettier/local"); + +test("API resolveConfigFile", async () => { + const result = await prettier.resolveConfigFile(); + expect(result).toEqual(path.join(__dirname, "../../.prettierrc")); +}); + +test("API resolveConfigFile.sync", () => { + const result = prettier.resolveConfigFile.sync(); + expect(result).toEqual(path.join(__dirname, "../../.prettierrc")); +}); diff --git a/tests_integration/__tests__/stdin-filepath.js b/tests_integration/__tests__/stdin-filepath.js index 863151be3..32cb97e23 100644 --- a/tests_integration/__tests__/stdin-filepath.js +++ b/tests_integration/__tests__/stdin-filepath.js @@ -1,5 +1,6 @@ "use strict"; +const { isCI } = require("ci-info"); const runPrettier = require("../runPrettier"); describe("format correctly if stdin content compatible with stdin-filepath", () => { @@ -64,6 +65,56 @@ function f() { }); }); +describe("apply editorconfig for stdin-filepath with a deep path", () => { + runPrettier( + "cli", + ["--stdin-filepath", "config/editorconfig/" + "a/".repeat(30) + "three.js"], + { + input: ` +function f() { + console.log("should be indented with a tab"); +} +`.trim(), // js + } + ).test({ + status: 0, + }); +}); + +if (isCI) { + describe("apply editorconfig for stdin-filepath in root", () => { + const code = ` +function f() { + console.log("should be indented with a tab"); +} +`.trim(); + runPrettier("cli", ["--stdin-filepath", "/foo.js"], { + input: code, // js + }).test({ + status: 0, + stdout: code + "\n", + stderr: "", + write: [], + }); + }); +} + +describe("apply editorconfig for stdin-filepath with a deep path", () => { + runPrettier( + "cli", + ["--stdin-filepath", "config/editorconfig/" + "a/".repeat(30) + "three.js"], + { + input: ` +function f() { + console.log("should be indented with a tab"); +} +`.trim(), // js + } + ).test({ + status: 0, + }); +}); + describe("don’t apply editorconfig outside project for stdin-filepath with nonexistent directory", () => { runPrettier( "cli", diff --git a/tests_integration/__tests__/third-party.js b/tests_integration/__tests__/third-party.js index aef027002..8dcb6079a 100644 --- a/tests_integration/__tests__/third-party.js +++ b/tests_integration/__tests__/third-party.js @@ -2,7 +2,7 @@ const path = require("path"); const { thirdParty } = require("../env"); -const { cosmiconfig, cosmiconfigSync } = require(thirdParty); +const { cosmiconfig, cosmiconfigSync, isCI } = require(thirdParty); expect.addSnapshotSerializer(require("../path-serializer")); @@ -62,3 +62,7 @@ describe("cosmiconfig", () => { }).toThrowErrorMatchingSnapshot(); }); }); + +test("isCI", () => { + expect(typeof isCI()).toEqual("boolean"); +}); diff --git a/tests_integration/cli/config/invalid/type-error/.prettierrc b/tests_integration/cli/config/invalid/type-error/.prettierrc new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/tests_integration/cli/config/invalid/type-error/.prettierrc @@ -0,0 +1 @@ +1 diff --git a/tests_integration/cli/config/overrides-exclude-files/.prettierrc b/tests_integration/cli/config/overrides-exclude-files/.prettierrc new file mode 100644 index 000000000..ca91ae40b --- /dev/null +++ b/tests_integration/cli/config/overrides-exclude-files/.prettierrc @@ -0,0 +1,19 @@ +{ + "singleQuote": true, + "trailingComma": "all", + "overrides": [ + { + "files": ["*.js"], + "options": { + "trailingComma": "es5" + } + }, + { + "files": ["*.js"], + "excludeFiles": ["single-quote.js"], + "options": { + "singleQuote": false + } + } + ] +}