Files
test-repo/tests/integration/run-prettier.js
T

164 lines
3.9 KiB
JavaScript

import path from "node:path";
import { Worker } from "node:worker_threads";
import stripAnsi from "strip-ansi";
import createEsmUtils from "esm-utils";
import { prettierCli, thirdParty } from "./env.js";
const { __dirname, require } = createEsmUtils(import.meta);
const CLI_WORKER_FILE = require.resolve("./cli-worker.js");
const streamToString = (stream) =>
new Promise((resolve, reject) => {
let result = "";
stream.on("data", (data) => {
result += data.toString();
});
stream.on("end", () => {
resolve(result);
});
stream.on("error", (error) => {
reject(error);
});
});
function runCliWorker(dir, args, options) {
const result = {
status: undefined,
stdout: "",
stderr: "",
write: [],
};
const worker = new Worker(CLI_WORKER_FILE, {
argv: args,
execArgv: ["--trace-deprecation"],
stdout: true,
stderr: true,
env: {
PRETTIER_DIR: process.env.PRETTIER_DIR,
},
workerData: {
dir,
prettierCli,
thirdParty,
options,
},
trackUnmanagedFds: false,
});
worker.on("message", ({ action, data }) => {
if (action === "write-file") {
result.write.push(data);
}
});
return new Promise((resolve, reject) => {
worker.on("exit", async (code) => {
result.status = code;
result.stdout = await streamToString(worker.stdout);
result.stderr = await streamToString(worker.stderr);
resolve(result);
});
worker.on("error", (error) => {
reject(error);
});
worker.postMessage("run");
});
}
async function run(dir, args, options) {
dir = normalizeDir(dir);
args = Array.isArray(args) ? args : [args];
// Worker doesn't support `chdir`
const cwd = process.cwd();
process.chdir(dir);
try {
return await runCliWorker(dir, args, options, cwd);
} finally {
process.chdir(cwd);
}
}
let runningCli;
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,
then(onFulfilled, onRejected) {
return runCli().then(onFulfilled, onRejected);
},
};
return getters;
function runCli() {
if (runningCli) {
throw new Error("Please wait for previous CLI to exit.");
}
if (!promise) {
promise = run(dir, args, options).finally(() => {
runningCli = undefined;
});
runningCli = promise;
}
return promise;
}
function testResult(testOptions) {
for (const name of ["status", "stdout", "stderr", "write"]) {
test(`${options.title || ""}(${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
// If ignoreLineEndings is specified, \r is simply deleted instead
typeof result[name] === "string"
? options.ignoreLineEndings
? stripAnsi(result[name]).replace(/\r/g, "")
: stripAnsi(result[name]).replace(/\r/g, "/*CR*/")
: result[name];
if (name in testOptions) {
if (name === "status" && testOptions[name] === "non-zero") {
expect(value).not.toBe(0);
} else if (typeof testOptions[name] === "function") {
testOptions[name](value);
} else {
expect(value).toEqual(testOptions[name]);
}
} else {
expect(value).toMatchSnapshot();
}
});
}
return getters;
}
}
function normalizeDir(dir) {
const isRelative = dir[0] !== "/";
return isRelative ? path.resolve(__dirname, dir) : dir;
}
export default runPrettier;