diff --git a/bin/prettier.js b/bin/prettier.js index 79fe9b23705a..7f3f91780b41 100755 --- a/bin/prettier.js +++ b/bin/prettier.js @@ -2,4 +2,4 @@ "use strict"; -require("../src/cli").run(process.argv.slice(2)); +module.exports = require("../src/cli").run(process.argv.slice(2)); diff --git a/src/cli/index.js b/src/cli/index.js index b38f6f511949..7ea19bd3abcf 100644 --- a/src/cli/index.js +++ b/src/cli/index.js @@ -8,7 +8,7 @@ const stringify = require("fast-json-stable-stringify"); const prettier = require("../index"); const core = require("./core"); -function run(rawArguments) { +async function run(rawArguments) { // Create a default level logger, so we can log errors during `logLevel` parsing let logger = core.createLogger(); diff --git a/tests/integration/__tests__/__snapshots__/early-exit.js.snap b/tests/integration/__tests__/__snapshots__/early-exit.js.snap index 832a1af9f280..4faab0a77f4e 100644 --- a/tests/integration/__tests__/__snapshots__/early-exit.js.snap +++ b/tests/integration/__tests__/__snapshots__/early-exit.js.snap @@ -1,14 +1,14 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`node version error (stderr) 1`] = ` -"prettier requires at least version 10.13.0 of Node, please upgrade -" +exports[`node version error 1`] = ` +Object { + "stderr": "prettier requires at least version 10.13.0 of Node, please upgrade +", + "stdout": "", + "write": Array [], +} `; -exports[`node version error (stdout) 1`] = `""`; - -exports[`node version error (write) 1`] = `Array []`; - exports[`show detailed usage with --help l (alias) (stderr) 1`] = `""`; exports[`show detailed usage with --help l (alias) (stdout) 1`] = ` diff --git a/tests/integration/__tests__/__snapshots__/plugin-options-string.js.snap b/tests/integration/__tests__/__snapshots__/plugin-options-string.js.snap index df76a8fa3423..2ed7ae8b698f 100644 --- a/tests/integration/__tests__/__snapshots__/plugin-options-string.js.snap +++ b/tests/integration/__tests__/__snapshots__/plugin-options-string.js.snap @@ -1,6 +1,19 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[` 1`] = ` +exports[`show detailed external option with \`--help foo-string\` (stderr) 1`] = `""`; + +exports[`show detailed external option with \`--help foo-string\` (stdout) 1`] = ` +"--foo-string + + foo description + +Default: bar +" +`; + +exports[`show detailed external option with \`--help foo-string\` (write) 1`] = `Array []`; + +exports[`show external options with \`--help\` 1`] = ` "Snapshot Diff: - First value + Second value @@ -28,16 +41,3 @@ exports[` 1`] = ` --prose-wrap How to wrap prose." `; - -exports[`show detailed external option with \`--help foo-string\` (stderr) 1`] = `""`; - -exports[`show detailed external option with \`--help foo-string\` (stdout) 1`] = ` -"--foo-string - - foo description - -Default: bar -" -`; - -exports[`show detailed external option with \`--help foo-string\` (write) 1`] = `Array []`; diff --git a/tests/integration/__tests__/__snapshots__/plugin-options.js.snap b/tests/integration/__tests__/__snapshots__/plugin-options.js.snap index 93d8477e51d7..276c950e742e 100644 --- a/tests/integration/__tests__/__snapshots__/plugin-options.js.snap +++ b/tests/integration/__tests__/__snapshots__/plugin-options.js.snap @@ -1,34 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[` 1`] = ` -"Snapshot Diff: -- First value -+ Second value - -@@ -20,18 +20,20 @@ - Control how Prettier formats quoted code embedded in the file. - Defaults to auto. - --end-of-line - Which end of line characters to apply. - Defaults to lf. -+ --foo-option foo description -+ Defaults to bar. - --html-whitespace-sensitivity - How to handle whitespaces in HTML. - Defaults to css. - --jsx-bracket-same-line Put > on the last line instead of at a new line. - Defaults to false. - --jsx-single-quote Use single quotes in JSX. - Defaults to false. -- --parser -+ --parser - Which parser to use. - --print-width The line length where Prettier will try wrap. - Defaults to 80. - --prose-wrap - How to wrap prose." -`; - exports[`include plugin's parsers to the values of the \`parser\` option\` (stderr) 1`] = `""`; exports[`include plugin's parsers to the values of the \`parser\` option\` (stdout) 1`] = ` @@ -83,3 +54,32 @@ Default: bar `; exports[`show detailed external option with \`--help foo-option\` (write) 1`] = `Array []`; + +exports[`show external options with \`--help\` 1`] = ` +"Snapshot Diff: +- First value ++ Second value + +@@ -20,18 +20,20 @@ + Control how Prettier formats quoted code embedded in the file. + Defaults to auto. + --end-of-line + Which end of line characters to apply. + Defaults to lf. ++ --foo-option foo description ++ Defaults to bar. + --html-whitespace-sensitivity + How to handle whitespaces in HTML. + Defaults to css. + --jsx-bracket-same-line Put > on the last line instead of at a new line. + Defaults to false. + --jsx-single-quote Use single quotes in JSX. + Defaults to false. +- --parser ++ --parser + Which parser to use. + --print-width The line length where Prettier will try wrap. + Defaults to 80. + --prose-wrap + How to wrap prose." +`; diff --git a/tests/integration/__tests__/check.js b/tests/integration/__tests__/check.js index 87773bff4ef0..4a1e3eebd387 100644 --- a/tests/integration/__tests__/check.js +++ b/tests/integration/__tests__/check.js @@ -44,5 +44,7 @@ describe("--checks works in CI just as in a non-TTY mode", () => { status: 1, }); - expect(result0.stdout).toEqual(result1.stdout); + test("Should have same stdout", async () => { + expect(await result0.stdout).toEqual(await result1.stdout); + }); }); diff --git a/tests/integration/__tests__/early-exit.js b/tests/integration/__tests__/early-exit.js index 7b623828afc8..c9d068becda6 100644 --- a/tests/integration/__tests__/early-exit.js +++ b/tests/integration/__tests__/early-exit.js @@ -90,14 +90,21 @@ describe("throw error and show usage with something unexpected", () => { }); }); -describe("node version error", () => { +test("node version error", async () => { const originalProcessVersion = process.version; + try { Object.defineProperty(process, "version", { value: "v8.0.0", writable: false, }); - runPrettier("cli", ["--help"]).test({ status: 1 }); + const result = runPrettier("cli", ["--help"]); + expect(await result.status).toEqual(1); + const snapshot = {}; + for (const name of ["stderr", "stdout", "write"]) { + snapshot[name] = await result[name]; + } + expect(snapshot).toMatchSnapshot(); } finally { Object.defineProperty(process, "version", { value: originalProcessVersion, diff --git a/tests/integration/__tests__/list-different.js b/tests/integration/__tests__/list-different.js index 2774d6a865f1..c767e6d4dd25 100644 --- a/tests/integration/__tests__/list-different.js +++ b/tests/integration/__tests__/list-different.js @@ -44,5 +44,7 @@ describe("--list-different works in CI just as in a non-TTY mode", () => { status: 1, }); - expect(result0.stdout).toEqual(result1.stdout); + test("Should be the same", async () => { + expect(await result0.stdout).toEqual(await result1.stdout); + }); }); diff --git a/tests/integration/__tests__/loglevel.js b/tests/integration/__tests__/loglevel.js index 11280a8a963e..54b854dc4364 100644 --- a/tests/integration/__tests__/loglevel.js +++ b/tests/integration/__tests__/loglevel.js @@ -3,20 +3,20 @@ const stripAnsi = require("strip-ansi"); const runPrettier = require("../runPrettier"); -test("do not show logs with --loglevel silent", () => { - runPrettierWithLogLevel("silent", null); +test("do not show logs with --loglevel silent", async () => { + await runPrettierWithLogLevel("silent", null); }); -test("do not show warnings with --loglevel error", () => { - runPrettierWithLogLevel("error", ["[error]"]); +test("do not show warnings with --loglevel error", async () => { + await runPrettierWithLogLevel("error", ["[error]"]); }); -test("show errors and warnings with --loglevel warn", () => { - runPrettierWithLogLevel("warn", ["[error]", "[warn]"]); +test("show errors and warnings with --loglevel warn", async () => { + await runPrettierWithLogLevel("warn", ["[error]", "[warn]"]); }); -test("show all logs with --loglevel debug", () => { - runPrettierWithLogLevel("debug", ["[error]", "[warn]", "[debug]"]); +test("show all logs with --loglevel debug", async () => { + await runPrettierWithLogLevel("debug", ["[error]", "[warn]", "[debug]"]); }); describe("--write with --loglevel=silent doesn't log filenames", () => { @@ -37,7 +37,7 @@ describe("Should use default level logger to log `--loglevel` error", () => { }); }); -function runPrettierWithLogLevel(logLevel, patterns) { +async function runPrettierWithLogLevel(logLevel, patterns) { const result = runPrettier("cli/loglevel", [ "--loglevel", logLevel, @@ -47,9 +47,9 @@ function runPrettierWithLogLevel(logLevel, patterns) { "not-found.js", ]); - expect(result.status).toEqual(2); + expect(await result.status).toEqual(2); - const stderr = stripAnsi(result.stderr); + const stderr = stripAnsi(await result.stderr); if (patterns) { for (const pattern of patterns) { diff --git a/tests/integration/__tests__/patterns-dirs.js b/tests/integration/__tests__/patterns-dirs.js index 9d500f746a98..29806ee081bc 100644 --- a/tests/integration/__tests__/patterns-dirs.js +++ b/tests/integration/__tests__/patterns-dirs.js @@ -92,16 +92,16 @@ if (path.sep === "/") { const base = path.resolve(__dirname, "../cli/patterns-dirs"); - // We can't commit these dirs without causing problems on Windows. + describe("Backslashes in names", () => { + // We can't commit these dirs without causing problems on Windows. - // TODO: these should be moved to a `beforeAll`, but for that to be possible, - // `runPrettier` should be refactored to use `describe` and `beforeEach` for doing setup. - fs.mkdirSync(path.resolve(base, "test-a\\")); - fs.writeFileSync(path.resolve(base, "test-a\\", "test.js"), "x"); - fs.mkdirSync(path.resolve(base, "test-b\\?")); - fs.writeFileSync(path.resolve(base, "test-b\\?", "test.js"), "x"); + beforeAll(() => { + fs.mkdirSync(path.resolve(base, "test-a\\")); + fs.writeFileSync(path.resolve(base, "test-a\\", "test.js"), "x"); + fs.mkdirSync(path.resolve(base, "test-b\\?")); + fs.writeFileSync(path.resolve(base, "test-b\\?", "test.js"), "x"); + }); - describe("Backslashes in names", () => { afterAll(() => { fs.unlinkSync(path.resolve(base, "test-a\\", "test.js")); fs.rmdirSync(path.resolve(base, "test-a\\")); diff --git a/tests/integration/__tests__/piped-output.js b/tests/integration/__tests__/piped-output.js index 173cd72e1357..81604e21acb3 100644 --- a/tests/integration/__tests__/piped-output.js +++ b/tests/integration/__tests__/piped-output.js @@ -19,8 +19,12 @@ describe("output with --check + unformatted differs when piped", () => { status: 0, }); - expect(result0.stdout.length).toBeGreaterThan(result1.stdout.length); - expect(result0.write).toEqual(result1.write); + test("Result", async () => { + expect((await result0.stdout).length).toBeGreaterThan( + (await result1.stdout).length + ); + expect(await result0.write).toEqual(await result1.write); + }); }); describe("no file diffs with --check + formatted file", () => { @@ -40,9 +44,13 @@ describe("no file diffs with --check + formatted file", () => { status: 0, }); - expect(result0.stdout).not.toEqual(result1.stdout); - expect(result0.stdout.length).toBeGreaterThan(result1.stdout.length); - expect(result0.write).toEqual(result1.write); + test("Result", async () => { + expect(await result0.stdout).not.toEqual(await result1.stdout); + expect((await result0.stdout).length).toBeGreaterThan( + (await result1.stdout).length + ); + expect(await result0.write).toEqual(await result1.write); + }); }); describe("output with --list-different + unformatted differs when piped", () => { @@ -62,8 +70,12 @@ describe("output with --list-different + unformatted differs when piped", () => status: 0, }); - expect(result0.stdout.length).toBeGreaterThan(result1.stdout.length); - expect(result0.write).toEqual(result1.write); + test("Result", async () => { + expect((await result0.stdout).length).toBeGreaterThan( + (await result1.stdout).length + ); + expect(await result0.write).toEqual(await result1.write); + }); }); describe("no file diffs with --list-different + formatted file", () => { @@ -83,7 +95,11 @@ describe("no file diffs with --list-different + formatted file", () => { status: 0, }); - expect(result0.stdout).not.toEqual(result1.stdout); - expect(result0.stdout.length).toBeGreaterThan(result1.stdout.length); - expect(result0.write).toEqual(result1.write); + test("Result", async () => { + expect(await result0.stdout).not.toEqual(await result1.stdout); + expect((await result0.stdout).length).toBeGreaterThan( + (await result1.stdout).length + ); + expect(await result0.write).toEqual(await result1.write); + }); }); diff --git a/tests/integration/__tests__/plugin-options-string.js b/tests/integration/__tests__/plugin-options-string.js index 96e3008fa6c9..4d3a83dbd051 100644 --- a/tests/integration/__tests__/plugin-options-string.js +++ b/tests/integration/__tests__/plugin-options-string.js @@ -3,10 +3,10 @@ const snapshotDiff = require("snapshot-diff"); const runPrettier = require("../runPrettier"); -describe("show external options with `--help`", () => { - const originalStdout = runPrettier("plugins/options-string", ["--help"]) +test("show external options with `--help`", async () => { + const originalStdout = await runPrettier("plugins/options-string", ["--help"]) .stdout; - const pluggedStdout = runPrettier("plugins/options-string", [ + const pluggedStdout = await runPrettier("plugins/options-string", [ "--help", "--plugin=./plugin", ]).stdout; diff --git a/tests/integration/__tests__/plugin-options.js b/tests/integration/__tests__/plugin-options.js index 209bed0ac2fc..39aa86b60541 100644 --- a/tests/integration/__tests__/plugin-options.js +++ b/tests/integration/__tests__/plugin-options.js @@ -3,12 +3,14 @@ const snapshotDiff = require("snapshot-diff"); const runPrettier = require("../runPrettier"); -describe("show external options with `--help`", () => { - const originalStdout = runPrettier("plugins/options", ["--help"]).stdout; - const pluggedStdout = runPrettier("plugins/options", [ +test("show external options with `--help`", async () => { + const originalStdout = await runPrettier("plugins/options", ["--help"]) + .stdout; + const pluggedStdout = await runPrettier("plugins/options", [ "--help", "--plugin=./plugin", ]).stdout; + expect(snapshotDiff(originalStdout, pluggedStdout)).toMatchSnapshot(); }); diff --git a/tests/integration/runPrettier.js b/tests/integration/runPrettier.js index 7c83ae5dec31..d8edb2773e12 100644 --- a/tests/integration/runPrettier.js +++ b/tests/integration/runPrettier.js @@ -6,7 +6,7 @@ const stripAnsi = require("strip-ansi"); const { SynchronousPromise } = require("synchronous-promise"); const { prettierCli, thirdParty } = require("./env"); -function runPrettier(dir, args = [], options = {}) { +async function run(dir, args, options) { args = Array.isArray(args) ? args : [args]; let status; @@ -99,7 +99,7 @@ function runPrettier(dir, args = [], options = {}) { .mockImplementation(() => process.cwd()); try { - require(prettierCli); + await require(prettierCli); status = (status === undefined ? process.exitCode : status) || 0; } catch (error) { status = 1; @@ -113,11 +113,59 @@ function runPrettier(dir, args = [], options = {}) { jest.restoreAllMocks(); } - const result = { status, stdout, stderr, write }; + return { status, stdout, stderr, write }; + + function appendStdout(text) { + if (status === undefined) { + stdout += text; + } + } + function appendStderr(text) { + if (status === undefined) { + stderr += text; + } + } +} + +let hasRunningCli = false; +function runPrettier(dir, args = [], options = {}) { + let promise; + const getters = { + get status() { + return runCli().then(({ status }) => status); + }, + get stdout() { + return runCli().then(({ stdout }) => stdout); + }, + get stderr() { + return runCli().then(({ stderr }) => stderr); + }, + get write() { + return runCli().then(({ write }) => write); + }, + test: testResult, + }; - const testResult = (testOptions) => { - for (const name of Object.keys(result)) { - test(`(${name})`, () => { + return getters; + + function runCli() { + if (hasRunningCli) { + throw new Error("Please wait for previous CLI to exit."); + } + + if (!promise) { + hasRunningCli = true; + promise = run(dir, args, options).finally(() => { + hasRunningCli = false; + }); + } + return promise; + } + + function testResult(testOptions) { + for (const name of ["status", "stdout", "stderr", "write"]) { + test(`(${name})`, async () => { + const result = await runCli(); const value = // \r is trimmed from jest snapshots by default; // manually replacing this character with /*CR*/ to test its true presence @@ -139,20 +187,7 @@ function runPrettier(dir, args = [], options = {}) { }); } - return result; - }; - - return { test: testResult, ...result }; - - function appendStdout(text) { - if (status === undefined) { - stdout += text; - } - } - function appendStderr(text) { - if (status === undefined) { - stderr += text; - } + return getters; } }