prettier/scripts/sync-flow-tests.js

130 lines
3.2 KiB
JavaScript

"use strict";
const fs = require("fs");
const flowParser = require("flow-parser");
const globby = require("globby");
const mkdirp = require("mkdirp");
const path = require("path");
const rimraf = require("rimraf");
const DEFAULT_SPEC_CONTENT = "run_spec(__dirname);\n";
const SPEC_FILE_NAME = "jsfmt.spec.js";
const FLOW_TESTS_DIR = path.join(__dirname, "..", "tests", "flow");
function tryParse(file, content) {
const ast = flowParser.parse(content, {
esproposal_class_instance_fields: true,
esproposal_class_static_fields: true,
esproposal_export_star_as: true
});
if (ast.errors.length > 0) {
const line = ast.errors[0].loc.start.line;
const column = ast.errors[0].loc.start.column;
const message = ast.errors[0].message;
return `${file}:${line}:${column}: ${message}`;
}
return null;
}
function syncTests(syncDir) {
const specFiles = globby.sync(
path.join(FLOW_TESTS_DIR, "**", SPEC_FILE_NAME)
);
const filesToCopy = globby.sync(path.join(syncDir, "**/*.js"));
if (filesToCopy.length === 0) {
throw new Error(
[
"Couldn't find any files to copy.",
`Please make sure that \`${syncDir}\` exists and contains the flow tests.`
].join("\n")
);
}
const specContents = specFiles.reduce((obj, specFile) => {
obj[specFile] = fs.readFileSync(specFile, "utf8");
return obj;
}, {});
const skipped = [];
rimraf.sync(FLOW_TESTS_DIR);
filesToCopy.forEach(file => {
const content = fs.readFileSync(file, "utf8");
const parseError = tryParse(file, content);
if (parseError) {
skipped.push(parseError);
return;
}
const newFile = path.join(FLOW_TESTS_DIR, path.relative(syncDir, file));
const dirname = path.dirname(newFile);
const specFile = path.join(dirname, SPEC_FILE_NAME);
const specContent = specContents[specFile] || DEFAULT_SPEC_CONTENT;
mkdirp.sync(dirname);
fs.writeFileSync(newFile, content);
fs.writeFileSync(specFile, specContent);
});
return skipped;
}
function run(argv) {
if (argv.length !== 1) {
console.error(
[
"You must provide the path to a flow tests directory to sync from!",
"Example: node scripts/sync-flow-tests.js ../flow/tests/"
].join("\n")
);
return 1;
}
const syncDir = argv[0];
let skipped = [];
try {
skipped = syncTests(syncDir);
} catch (error) {
console.error(`Failed to sync.\n${error}`);
return 1;
}
if (skipped.length > 0) {
console.log(
[
"Some files were skipped due to syntax errors.",
"This is expected since flow tests for handling invalid code,",
"but that's not interesting for Prettier's tests.",
"This is the skipped stuff:",
""
]
.concat(skipped, "")
.join("\n")
);
}
console.log(
[
"Done syncing! Now you need to:",
"",
`1. Optional: Adjust some ${SPEC_FILE_NAME} files.`,
"2. Run `jest -u` to create snapshots.",
"3. Run `git diff` to check how tests and snapshots have changed",
"4. Take a look at new snapshots to see if they're OK."
].join("\n")
);
return 0;
}
if (require.main === module) {
const exitCode = run(process.argv.slice(2));
process.exit(exitCode);
}