"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); }