From 69d26582e7be8177f754ed6a52170c9d9772a2bd Mon Sep 17 00:00:00 2001 From: fisker Cheung Date: Mon, 10 Aug 2020 22:17:51 +0800 Subject: [PATCH] Refactor test (#8940) --- tests_config/run_spec.js | 313 ++++++++++-------- .../utils/compose-options-for-snapshot.js | 2 + 2 files changed, 175 insertions(+), 140 deletions(-) diff --git a/tests_config/run_spec.js b/tests_config/run_spec.js index 3733b48bb..9643287a1 100644 --- a/tests_config/run_spec.js +++ b/tests_config/run_spec.js @@ -50,6 +50,34 @@ const unstableTests = new Map( }) ); +const isUnstable = (filename, options) => { + const testFunction = unstableTests.get(filename); + + if (!testFunction) { + return false; + } + + return testFunction(options); +}; + +const shouldThrowOnVerify = (filename, options) => { + if (options.parser !== "babel-ts") { + return false; + } + + const { disableBabelTS } = options; + + if (disableBabelTS === true) { + return true; + } + + if (Array.isArray(disableBabelTS) && disableBabelTS.includes(filename)) { + return true; + } + + return false; +}; + const isTestDirectory = (dirname, name) => dirname.startsWith(path.join(__dirname, "../tests", name)); @@ -113,182 +141,156 @@ global.run_spec = (fixtures, parsers, options) => { } const stringifiedOptions = stringifyOptionsForTitle(options); + const [parser, ...verifyParsers] = parsers; + + if (parsers.includes("typescript") && !parsers.includes("babel-ts")) { + verifyParsers.push("babel-ts"); + } for (const { name, filename, code, output } of [...files, ...snippets]) { describe(`${name}${ stringifiedOptions ? ` - ${stringifiedOptions}` : "" }`, () => { - let rangeStart; - let rangeEnd; - let cursorOffset; - - const source = (TEST_CRLF ? code.replace(/\n/g, "\r\n") : code) - .replace(RANGE_START_PLACEHOLDER, (match, offset) => { - rangeStart = offset; - return ""; - }) - .replace(RANGE_END_PLACEHOLDER, (match, offset) => { - rangeEnd = offset; - return ""; - }); - - const input = source.replace(CURSOR_PLACEHOLDER, (match, offset) => { - cursorOffset = offset; - return ""; - }); - - const baseOptions = { + const formatOptions = { printWidth: 80, ...options, - rangeStart, - rangeEnd, - cursorOffset, + filepath: filename, + parser, }; - const mainOptions = { - ...baseOptions, - ...(IS_PARSER_INFERENCE_TESTS - ? { filepath: filename } - : { parser: parsers[0] }), - }; - - const hasEndOfLine = "endOfLine" in mainOptions; if (IS_ERROR_TESTS) { test("error test", () => { expect(() => { - format(input, filename, mainOptions); + format(code, formatOptions); }).toThrowErrorMatchingSnapshot(); }); return; } - const formattedWithCursor = format(input, filename, mainOptions); - const formatted = formattedWithCursor.replace(CURSOR_PLACEHOLDER, ""); - const visualizedOutput = visualizeEndOfLine(formattedWithCursor); + const eolReplacedCode = TEST_CRLF ? code.replace(/\n/g, "\r\n") : code; + const firstFormat = format(eolReplacedCode, formatOptions); test("format", () => { - expect(visualizedOutput).toEqual( - visualizeEndOfLine(consistentEndOfLine(formattedWithCursor)) + // Make sure output has consistent EOL + expect(firstFormat.eolVisualizedOutput).toEqual( + visualizeEndOfLine(consistentEndOfLine(firstFormat.outputWithCursor)) ); + if (typeof output === "string") { - expect(formatted).toEqual(output); - } else { - let codeForSnapshot = hasEndOfLine - ? code - .replace(RANGE_START_PLACEHOLDER, "") - .replace(RANGE_END_PLACEHOLDER, "") - : source; - let codeOffset = 0; - let resultForSnapshot = formattedWithCursor; - - if ( - typeof baseOptions.rangeStart === "number" || - typeof baseOptions.rangeEnd === "number" - ) { - if (TEST_CRLF && hasEndOfLine) { - codeForSnapshot = codeForSnapshot.replace(/\n/g, "\r\n"); - } - codeForSnapshot = visualizeRange(codeForSnapshot, baseOptions); - codeOffset = codeForSnapshot.match(/^>?\s+1 \| /)[0].length; - } - - // When `TEST_CRLF` and `endOfLine: "auto"`, the eol is always `\r\n`, - // Replace it with guess result from original input - let resultNote = ""; - if (mainOptions.endOfLine === "auto") { - const { - guessEndOfLine, - convertEndOfLineToChars, - } = require("../src/common/end-of-line"); - const originalAutoResult = convertEndOfLineToChars( - guessEndOfLine(code) - ); - if (originalAutoResult !== "\r\n") { - resultNote += - "** The EOL of output might not real when `TEST_CRLF` **"; - - if (TEST_CRLF) { - resultForSnapshot = resultForSnapshot.replace( - /\r\n?/g, - originalAutoResult - ); - } - } - } - - if (hasEndOfLine) { - codeForSnapshot = visualizeEndOfLine(codeForSnapshot); - resultForSnapshot = visualizeEndOfLine(resultForSnapshot); - } - - if (resultNote) { - resultForSnapshot = `${resultNote}\n${resultForSnapshot}`; - } - - expect( - createSnapshot( - codeForSnapshot, - resultForSnapshot, - composeOptionsForSnapshot(baseOptions, parsers), - { codeOffset } - ) - ).toMatchSnapshot(); + expect(firstFormat.output).toEqual(output); + return; } + + const hasEndOfLine = "endOfLine" in formatOptions; + let codeForSnapshot = hasEndOfLine + ? code + .replace(RANGE_START_PLACEHOLDER, "") + .replace(RANGE_END_PLACEHOLDER, "") + : firstFormat.inputWithCursor; + let codeOffset = 0; + let resultForSnapshot = firstFormat.outputWithCursor; + const { rangeStart, rangeEnd } = firstFormat.options; + + if (typeof rangeStart === "number" || typeof rangeEnd === "number") { + if (TEST_CRLF && hasEndOfLine) { + codeForSnapshot = codeForSnapshot.replace(/\n/g, "\r\n"); + } + codeForSnapshot = visualizeRange(codeForSnapshot, { + rangeStart, + rangeEnd, + }); + codeOffset = codeForSnapshot.match(/^>?\s+1 \| /)[0].length; + } + + // When `TEST_CRLF` and `endOfLine: "auto"`, the eol is always `\r\n`, + // Replace it with guess result from original input + let resultNote = ""; + if (formatOptions.endOfLine === "auto") { + const { + guessEndOfLine, + convertEndOfLineToChars, + } = require("../src/common/end-of-line"); + const originalAutoResult = convertEndOfLineToChars( + guessEndOfLine(code) + ); + if (originalAutoResult !== "\r\n") { + resultNote += + "** The EOL of output might not real when `TEST_CRLF` **"; + + if (TEST_CRLF) { + resultForSnapshot = resultForSnapshot.replace( + /\r\n?/g, + originalAutoResult + ); + } + } + } + + if (hasEndOfLine) { + codeForSnapshot = visualizeEndOfLine(codeForSnapshot); + resultForSnapshot = visualizeEndOfLine(resultForSnapshot); + } + + if (resultNote) { + resultForSnapshot = `${resultNote}\n${resultForSnapshot}`; + } + + expect( + createSnapshot( + codeForSnapshot, + resultForSnapshot, + composeOptionsForSnapshot(firstFormat.options, parsers), + { codeOffset } + ) + ).toMatchSnapshot(); }); - const parsersToVerify = parsers.slice(1); - if (parsers.includes("typescript") && !parsers.includes("babel-ts")) { - parsersToVerify.push("babel-ts"); - } - - for (const parser of parsersToVerify) { - const verifyOptions = { ...baseOptions, parser }; + for (const parser of verifyParsers) { + const verifyOptions = { ...firstFormat.options, parser }; + const verifyFormat = () => format(firstFormat.input, verifyOptions); test(`verify (${parser})`, () => { - if ( - parser === "babel-ts" && - options && - (options.disableBabelTS === true || - (Array.isArray(options.disableBabelTS) && - options.disableBabelTS.includes(name))) - ) { - expect(() => { - format(input, filename, verifyOptions); - }).toThrow(TEST_STANDALONE ? undefined : SyntaxError); - } else { - const verifyOutput = format(input, filename, verifyOptions); - expect(visualizeEndOfLine(verifyOutput)).toEqual(visualizedOutput); + if (shouldThrowOnVerify(name, verifyOptions)) { + expect(verifyFormat).toThrow( + TEST_STANDALONE ? undefined : SyntaxError + ); + return; } + + const { eolVisualizedOutput: verifyOutput } = verifyFormat(); + const { eolVisualizedOutput: firstOutput } = firstFormat; + expect(verifyOutput).toEqual(firstOutput); }); } - const isUnstable = unstableTests.get(filename); - const isUnstableTest = isUnstable && isUnstable(options || {}); + const isUnstableTest = isUnstable(filename, formatOptions); if ( DEEP_COMPARE && - (formatted !== input || isUnstableTest) && - typeof rangeStart === "undefined" && - typeof rangeEnd === "undefined" && - typeof cursorOffset === "undefined" && - !TEST_CRLF + (firstFormat.changed || isUnstableTest) && + // No range and cursor + firstFormat.input === eolReplacedCode ) { test("second format", () => { - const secondOutput = format(formatted, filename, mainOptions); + const { eolVisualizedOutput: firstOutput, output } = firstFormat; + const { eolVisualizedOutput: secondOutput } = format( + output, + formatOptions + ); if (isUnstableTest) { // To keep eye on failed tests, this assert never supposed to pass, // if it fails, just remove the file from `unstableTests` - expect(secondOutput).not.toEqual(formatted); + expect(secondOutput).not.toEqual(firstOutput); } else { - expect(secondOutput).toEqual(formatted); + expect(secondOutput).toEqual(firstOutput); } }); } - if (AST_COMPARE && formatted !== input) { + if (AST_COMPARE && firstFormat.changed) { test("compare AST", () => { - const { cursorOffset, ...parseOptions } = mainOptions; - const originalAst = parse(input, parseOptions); - const formattedAst = parse(formatted, parseOptions); + const { input, output } = firstFormat; + const originalAst = parse(input, formatOptions); + const formattedAst = parse(output, formatOptions); expect(formattedAst).toEqual(originalAst); }); } @@ -300,15 +302,46 @@ function parse(source, options) { return prettier.__debug.parse(source, options, /* massage */ true).ast; } -function format(source, filename, options) { - const result = prettier.formatWithCursor(source, { - filepath: filename, +function format(text, options) { + options = { ...options, + }; + + const inputWithCursor = text + .replace(RANGE_START_PLACEHOLDER, (match, offset) => { + options.rangeStart = offset; + return ""; + }) + .replace(RANGE_END_PLACEHOLDER, (match, offset) => { + options.rangeEnd = offset; + return ""; + }); + + const input = inputWithCursor.replace(CURSOR_PLACEHOLDER, (match, offset) => { + options.cursorOffset = offset; + return ""; }); - return options.cursorOffset >= 0 - ? result.formatted.slice(0, result.cursorOffset) + + const result = prettier.formatWithCursor(input, options); + const output = result.formatted; + + const outputWithCursor = + options.cursorOffset >= 0 + ? output.slice(0, result.cursorOffset) + CURSOR_PLACEHOLDER + - result.formatted.slice(result.cursorOffset) - : result.formatted; + output.slice(result.cursorOffset) + : output; + const eolVisualizedOutput = visualizeEndOfLine(outputWithCursor); + + const changed = outputWithCursor !== inputWithCursor; + + return { + changed, + options, + input, + inputWithCursor, + output, + outputWithCursor, + eolVisualizedOutput, + }; } diff --git a/tests_config/utils/compose-options-for-snapshot.js b/tests_config/utils/compose-options-for-snapshot.js index 0ce8ce794..ed8205704 100644 --- a/tests_config/utils/compose-options-for-snapshot.js +++ b/tests_config/utils/compose-options-for-snapshot.js @@ -7,6 +7,8 @@ function composeOptionsForSnapshot(baseOptions, parsers) { cursorOffset, disableBabelTS, plugins, + filepath, + parser, ...snapshotOptions } = baseOptions;