Make babel-node a standalone package (#6023)
* Make babel-node a standalone package * New package `babel-node` previously `babel-cli/bin/babel-node` * updates
This commit is contained in:
parent
e32042f353
commit
6d965c0926
1
.gitignore
vendored
1
.gitignore
vendored
@ -23,6 +23,7 @@ package-lock.json
|
||||
!/packages/babel-runtime/helpers/es6/toArray.js
|
||||
/packages/babel-register/test/.babel
|
||||
/packages/babel-cli/test/tmp
|
||||
/packages/babel-node/test/tmp
|
||||
/packages/*/lib
|
||||
.nyc_output
|
||||
/babel.sublime-workspace
|
||||
|
||||
3
packages/babel-node/.npmignore
Normal file
3
packages/babel-node/.npmignore
Normal file
@ -0,0 +1,3 @@
|
||||
src
|
||||
test
|
||||
node_modules
|
||||
17
packages/babel-node/README.md
Normal file
17
packages/babel-node/README.md
Normal file
@ -0,0 +1,17 @@
|
||||
# babel-node
|
||||
|
||||
> A Babel-powered Node.js CLI
|
||||
|
||||
babel-node is a CLI that works exactly the same as the Node.js CLI, with the added benefit of compiling with Babel presets and plugins before running it.
|
||||
|
||||
## Install
|
||||
|
||||
```sh
|
||||
npm install --save-dev babel-node
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```sh
|
||||
babel-node [options] [ -e script | script.js ] [arguments]
|
||||
```
|
||||
3
packages/babel-node/bin/babel-node.js
Executable file
3
packages/babel-node/bin/babel-node.js
Executable file
@ -0,0 +1,3 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
require("../lib/babel-node");
|
||||
34
packages/babel-node/package.json
Normal file
34
packages/babel-node/package.json
Normal file
@ -0,0 +1,34 @@
|
||||
{
|
||||
"name": "babel-node",
|
||||
"version": "7.0.0-alpha.17",
|
||||
"description": "Babel command line",
|
||||
"author": "Sebastian McKenzie <sebmck@gmail.com>",
|
||||
"homepage": "https://babeljs.io/",
|
||||
"license": "MIT",
|
||||
"repository": "https://github.com/babel/babel/tree/master/packages/babel-node",
|
||||
"keywords": [
|
||||
"6to5",
|
||||
"babel",
|
||||
"es6",
|
||||
"transpile",
|
||||
"transpiler",
|
||||
"babel-cli",
|
||||
"compiler"
|
||||
],
|
||||
"dependencies": {
|
||||
"babel-core": "7.0.0-alpha.17",
|
||||
"babel-register": "7.0.0-alpha.17",
|
||||
"babel-polyfill": "7.0.0-alpha.17",
|
||||
"commander": "^2.8.1",
|
||||
"fs-readdir-recursive": "^1.0.0",
|
||||
"lodash": "^4.2.0",
|
||||
"output-file-sync": "^2.0.0",
|
||||
"v8flags": "^3.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-helper-fixtures": "7.0.0-alpha.17"
|
||||
},
|
||||
"bin": {
|
||||
"babel-node": "./bin/babel-node.js"
|
||||
}
|
||||
}
|
||||
186
packages/babel-node/src/_babel-node.js
Normal file
186
packages/babel-node/src/_babel-node.js
Normal file
@ -0,0 +1,186 @@
|
||||
import commander from "commander";
|
||||
import Module from "module";
|
||||
import { inspect } from "util";
|
||||
import path from "path";
|
||||
import repl from "repl";
|
||||
import * as babel from "babel-core";
|
||||
import vm from "vm";
|
||||
import "babel-polyfill";
|
||||
import register from "babel-register";
|
||||
|
||||
import pkg from "../package.json";
|
||||
|
||||
const program = new commander.Command("babel-node");
|
||||
|
||||
function collect(value, previousValue): Array<string> {
|
||||
// If the user passed the option with no value, like "babel-node file.js --presets", do nothing.
|
||||
if (typeof value !== "string") return previousValue;
|
||||
|
||||
const values = value.split(",");
|
||||
|
||||
return previousValue ? previousValue.concat(values) : values;
|
||||
}
|
||||
|
||||
/* eslint-disable max-len */
|
||||
program.option("-e, --eval [script]", "Evaluate script");
|
||||
program.option("-p, --print [code]", "Evaluate script and print result");
|
||||
program.option(
|
||||
"-o, --only [globs]",
|
||||
"A comma-separated list of glob patterns to compile",
|
||||
collect,
|
||||
);
|
||||
program.option(
|
||||
"-i, --ignore [globs]",
|
||||
"A comma-separated list of glob patterns to skip compiling",
|
||||
collect,
|
||||
);
|
||||
program.option(
|
||||
"-x, --extensions [extensions]",
|
||||
"List of extensions to hook into [.es6,.js,.es,.jsx,.mjs]",
|
||||
collect,
|
||||
);
|
||||
program.option("-w, --plugins [string]", "", collect);
|
||||
program.option("-b, --presets [string]", "", collect);
|
||||
/* eslint-enable max-len */
|
||||
|
||||
program.version(pkg.version);
|
||||
program.usage("[options] [ -e script | script.js ] [arguments]");
|
||||
program.parse(process.argv);
|
||||
|
||||
register({
|
||||
extensions: program.extensions,
|
||||
ignore: program.ignore,
|
||||
only: program.only,
|
||||
plugins: program.plugins,
|
||||
presets: program.presets,
|
||||
});
|
||||
|
||||
const replPlugin = ({ types: t }) => ({
|
||||
visitor: {
|
||||
ModuleDeclaration(path) {
|
||||
throw path.buildCodeFrameError("Modules aren't supported in the REPL");
|
||||
},
|
||||
|
||||
VariableDeclaration(path) {
|
||||
if (path.node.kind !== "var") {
|
||||
throw path.buildCodeFrameError(
|
||||
"Only `var` variables are supported in the REPL",
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
Program(path) {
|
||||
if (path.get("body").some(child => child.isExpressionStatement())) return;
|
||||
|
||||
// If the executed code doesn't evaluate to a value,
|
||||
// prevent implicit strict mode from printing 'use strict'.
|
||||
path.pushContainer(
|
||||
"body",
|
||||
t.expressionStatement(t.identifier("undefined")),
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const _eval = function(code, filename) {
|
||||
code = code.trim();
|
||||
if (!code) return undefined;
|
||||
|
||||
code = babel.transform(code, {
|
||||
filename: filename,
|
||||
presets: program.presets,
|
||||
plugins: (program.plugins || []).concat([replPlugin]),
|
||||
}).code;
|
||||
|
||||
return vm.runInThisContext(code, {
|
||||
filename: filename,
|
||||
});
|
||||
};
|
||||
|
||||
if (program.eval || program.print) {
|
||||
let code = program.eval;
|
||||
if (!code || code === true) code = program.print;
|
||||
|
||||
global.__filename = "[eval]";
|
||||
global.__dirname = process.cwd();
|
||||
|
||||
const module = new Module(global.__filename);
|
||||
module.filename = global.__filename;
|
||||
module.paths = Module._nodeModulePaths(global.__dirname);
|
||||
|
||||
global.exports = module.exports;
|
||||
global.module = module;
|
||||
global.require = module.require.bind(module);
|
||||
|
||||
const result = _eval(code, global.__filename);
|
||||
if (program.print) {
|
||||
const output = typeof result === "string" ? result : inspect(result);
|
||||
process.stdout.write(output + "\n");
|
||||
}
|
||||
} else {
|
||||
if (program.args.length) {
|
||||
// slice all arguments up to the first filename since they're babel args that we handle
|
||||
let args = process.argv.slice(2);
|
||||
|
||||
let i = 0;
|
||||
let ignoreNext = false;
|
||||
args.some(function(arg, i2) {
|
||||
if (ignoreNext) {
|
||||
ignoreNext = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (arg[0] === "-") {
|
||||
const parsedArg = program[arg.slice(2)];
|
||||
if (parsedArg && parsedArg !== true) {
|
||||
ignoreNext = true;
|
||||
}
|
||||
} else {
|
||||
i = i2;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
args = args.slice(i);
|
||||
|
||||
// make the filename absolute
|
||||
const filename = args[0];
|
||||
if (!path.isAbsolute(filename)) {
|
||||
args[0] = path.join(process.cwd(), filename);
|
||||
}
|
||||
|
||||
// add back on node and concat the sliced args
|
||||
process.argv = ["node"].concat(args);
|
||||
process.execArgv.unshift(__filename);
|
||||
|
||||
Module.runMain();
|
||||
} else {
|
||||
replStart();
|
||||
}
|
||||
}
|
||||
|
||||
function replStart() {
|
||||
repl.start({
|
||||
prompt: "> ",
|
||||
input: process.stdin,
|
||||
output: process.stdout,
|
||||
eval: replEval,
|
||||
useGlobal: true,
|
||||
});
|
||||
}
|
||||
|
||||
function replEval(code, context, filename, callback) {
|
||||
let err;
|
||||
let result;
|
||||
|
||||
try {
|
||||
if (code[0] === "(" && code[code.length - 1] === ")") {
|
||||
code = code.slice(1, -1); // remove "(" and ")"
|
||||
}
|
||||
|
||||
result = _eval(code, filename);
|
||||
} catch (e) {
|
||||
err = e;
|
||||
}
|
||||
|
||||
callback(err, result);
|
||||
}
|
||||
98
packages/babel-node/src/babel-node.js
Executable file
98
packages/babel-node/src/babel-node.js
Executable file
@ -0,0 +1,98 @@
|
||||
/**
|
||||
* This tiny wrapper file checks for known node flags and appends them
|
||||
* when found, before invoking the "real" _babel-node(1) executable.
|
||||
*/
|
||||
|
||||
import getV8Flags from "v8flags";
|
||||
import path from "path";
|
||||
|
||||
let args = [path.join(__dirname, "_babel-node")];
|
||||
|
||||
let babelArgs = process.argv.slice(2);
|
||||
let userArgs;
|
||||
|
||||
// separate node arguments from script arguments
|
||||
const argSeparator = babelArgs.indexOf("--");
|
||||
if (argSeparator > -1) {
|
||||
userArgs = babelArgs.slice(argSeparator); // including the --
|
||||
babelArgs = babelArgs.slice(0, argSeparator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace dashes with underscores in the v8Flag name
|
||||
* Also ensure that if the arg contains a value (e.g. --arg=true)
|
||||
* that only the flag is returned.
|
||||
*/
|
||||
function getNormalizedV8Flag(arg) {
|
||||
const matches = arg.match(/--(.+)/);
|
||||
|
||||
if (matches) {
|
||||
return `--${matches[1].replace(/-/g, "_")}`;
|
||||
}
|
||||
|
||||
return arg;
|
||||
}
|
||||
|
||||
getV8Flags(function(err, v8Flags) {
|
||||
babelArgs.forEach(function(arg) {
|
||||
const flag = arg.split("=")[0];
|
||||
|
||||
switch (flag) {
|
||||
case "-d":
|
||||
args.unshift("--debug");
|
||||
break;
|
||||
|
||||
case "debug":
|
||||
case "--debug":
|
||||
case "--debug-brk":
|
||||
case "--inspect":
|
||||
args.unshift(arg);
|
||||
break;
|
||||
|
||||
case "-gc":
|
||||
args.unshift("--expose-gc");
|
||||
break;
|
||||
|
||||
case "--nolazy":
|
||||
args.unshift(flag);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (
|
||||
v8Flags.indexOf(getNormalizedV8Flag(flag)) >= 0 ||
|
||||
arg.indexOf("--trace") === 0
|
||||
) {
|
||||
args.unshift(arg);
|
||||
} else {
|
||||
args.push(arg);
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
// append arguments passed after --
|
||||
if (argSeparator > -1) {
|
||||
args = args.concat(userArgs);
|
||||
}
|
||||
|
||||
try {
|
||||
const kexec = require("kexec");
|
||||
kexec(process.argv[0], args);
|
||||
} catch (err) {
|
||||
if (err.code !== "MODULE_NOT_FOUND") throw err;
|
||||
|
||||
const child_process = require("child_process");
|
||||
const proc = child_process.spawn(process.argv[0], args, {
|
||||
stdio: "inherit",
|
||||
});
|
||||
proc.on("exit", function(code, signal) {
|
||||
process.on("exit", function() {
|
||||
if (signal) {
|
||||
process.kill(process.pid, signal);
|
||||
} else {
|
||||
process.exit(code);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
4
packages/babel-node/test/fixtures/babel-node/--eval/options.json
vendored
Normal file
4
packages/babel-node/test/fixtures/babel-node/--eval/options.json
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"args": ["--eval", "console.log([1, 2, 3].map(x => x * x));"],
|
||||
"stdout": "[ 1, 4, 9 ]"
|
||||
}
|
||||
1
packages/babel-node/test/fixtures/babel-node/--extensions/in-files/foo.bar
vendored
Normal file
1
packages/babel-node/test/fixtures/babel-node/--extensions/in-files/foo.bar
vendored
Normal file
@ -0,0 +1 @@
|
||||
console.log([1, 2, 3].map(x => x * x));
|
||||
4
packages/babel-node/test/fixtures/babel-node/--extensions/options.json
vendored
Normal file
4
packages/babel-node/test/fixtures/babel-node/--extensions/options.json
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"args": ["foo", "--extensions", ".bar"],
|
||||
"stdout": "[ 1, 4, 9 ]"
|
||||
}
|
||||
4
packages/babel-node/test/fixtures/babel-node/--print/options.json
vendored
Normal file
4
packages/babel-node/test/fixtures/babel-node/--print/options.json
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"args": ["--print", "--eval", "([1, 2, 3].map(x => x * x))"],
|
||||
"stdout": "[ 1, 4, 9 ]"
|
||||
}
|
||||
1
packages/babel-node/test/fixtures/babel-node/arguments/in-files/bar.js
vendored
Normal file
1
packages/babel-node/test/fixtures/babel-node/arguments/in-files/bar.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
console.log(process.argv[2]);
|
||||
4
packages/babel-node/test/fixtures/babel-node/arguments/options.json
vendored
Normal file
4
packages/babel-node/test/fixtures/babel-node/arguments/options.json
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"args": ["bar", "foo"],
|
||||
"stdout": "foo"
|
||||
}
|
||||
2
packages/babel-node/test/fixtures/babel-node/directory/in-files/foo/index.js
vendored
Normal file
2
packages/babel-node/test/fixtures/babel-node/directory/in-files/foo/index.js
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
var foo = () => console.log("foo");
|
||||
foo();
|
||||
3
packages/babel-node/test/fixtures/babel-node/directory/options.json
vendored
Normal file
3
packages/babel-node/test/fixtures/babel-node/directory/options.json
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"args": ["foo"]
|
||||
}
|
||||
1
packages/babel-node/test/fixtures/babel-node/directory/stdout.txt
vendored
Normal file
1
packages/babel-node/test/fixtures/babel-node/directory/stdout.txt
vendored
Normal file
@ -0,0 +1 @@
|
||||
foo
|
||||
2
packages/babel-node/test/fixtures/babel-node/filename/in-files/bar.js
vendored
Normal file
2
packages/babel-node/test/fixtures/babel-node/filename/in-files/bar.js
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
var foo = () => console.log("foo");
|
||||
foo();
|
||||
3
packages/babel-node/test/fixtures/babel-node/filename/options.json
vendored
Normal file
3
packages/babel-node/test/fixtures/babel-node/filename/options.json
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"args": ["bar"]
|
||||
}
|
||||
1
packages/babel-node/test/fixtures/babel-node/filename/stdout.txt
vendored
Normal file
1
packages/babel-node/test/fixtures/babel-node/filename/stdout.txt
vendored
Normal file
@ -0,0 +1 @@
|
||||
foo
|
||||
4
packages/babel-node/test/fixtures/babel-node/no-strict/options.json
vendored
Normal file
4
packages/babel-node/test/fixtures/babel-node/no-strict/options.json
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"args": ["--eval","--print", "var a = 1;"],
|
||||
"stdout": "undefined"
|
||||
}
|
||||
2
packages/babel-node/test/fixtures/babel-node/require/in-files/bar2.js
vendored
Normal file
2
packages/babel-node/test/fixtures/babel-node/require/in-files/bar2.js
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
var bar = () => console.log("bar");
|
||||
bar();
|
||||
5
packages/babel-node/test/fixtures/babel-node/require/in-files/foo2.js
vendored
Normal file
5
packages/babel-node/test/fixtures/babel-node/require/in-files/foo2.js
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
import "./bar2";
|
||||
import "./not_node_modules";
|
||||
|
||||
var foo = () => console.log("foo");
|
||||
foo();
|
||||
10
packages/babel-node/test/fixtures/babel-node/require/in-files/not_node_modules.jsx
vendored
Normal file
10
packages/babel-node/test/fixtures/babel-node/require/in-files/not_node_modules.jsx
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
/*
|
||||
The purpose of this file is to test that the node_modules check in the require
|
||||
hook doesn't mistakenly exclude something like "not_node_modules". To pass, this
|
||||
file merely needs to be transpiled. The transpiled code won't, and doesn't need
|
||||
to, execute without error. It won't execute because React will be undefined.
|
||||
*/
|
||||
try {
|
||||
<Some jsx="element" />;
|
||||
}
|
||||
catch (e) {}
|
||||
3
packages/babel-node/test/fixtures/babel-node/require/options.json
vendored
Normal file
3
packages/babel-node/test/fixtures/babel-node/require/options.json
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"args": ["foo2"]
|
||||
}
|
||||
2
packages/babel-node/test/fixtures/babel-node/require/stdout.txt
vendored
Normal file
2
packages/babel-node/test/fixtures/babel-node/require/stdout.txt
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
bar
|
||||
foo
|
||||
4
packages/babel-node/test/fixtures/babel-node/v8Flag-dashed-with-param/options.json
vendored
Normal file
4
packages/babel-node/test/fixtures/babel-node/v8Flag-dashed-with-param/options.json
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"args": ["--expose-gc-as=garbageCollector", "--eval", "console.log(typeof global.garbageCollector)"],
|
||||
"stdout": "function"
|
||||
}
|
||||
4
packages/babel-node/test/fixtures/babel-node/v8Flag-dashed/options.json
vendored
Normal file
4
packages/babel-node/test/fixtures/babel-node/v8Flag-dashed/options.json
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"args": ["--expose-gc", "--eval", "console.log(typeof global.gc)"],
|
||||
"stdout": "function"
|
||||
}
|
||||
4
packages/babel-node/test/fixtures/babel-node/v8Flag-underscored-with-param/options.json
vendored
Normal file
4
packages/babel-node/test/fixtures/babel-node/v8Flag-underscored-with-param/options.json
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"args": ["--expose_gc_as=garbageCollector", "--eval", "console.log(typeof global.garbageCollector)"],
|
||||
"stdout": "function"
|
||||
}
|
||||
4
packages/babel-node/test/fixtures/babel-node/v8Flag-underscored/options.json
vendored
Normal file
4
packages/babel-node/test/fixtures/babel-node/v8Flag-underscored/options.json
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"args": ["--expose_gc", "--eval", "console.log(typeof global.gc)"],
|
||||
"stdout": "function"
|
||||
}
|
||||
213
packages/babel-node/test/index.js
Normal file
213
packages/babel-node/test/index.js
Normal file
@ -0,0 +1,213 @@
|
||||
const includes = require("lodash/includes");
|
||||
const readdir = require("fs-readdir-recursive");
|
||||
const helper = require("babel-helper-fixtures");
|
||||
const assert = require("assert");
|
||||
const rimraf = require("rimraf");
|
||||
const outputFileSync = require("output-file-sync");
|
||||
const child = require("child_process");
|
||||
const merge = require("lodash/merge");
|
||||
const path = require("path");
|
||||
const chai = require("chai");
|
||||
const fs = require("fs");
|
||||
|
||||
const fixtureLoc = path.join(__dirname, "fixtures");
|
||||
const tmpLoc = path.join(__dirname, "tmp");
|
||||
|
||||
const fileFilter = function(x) {
|
||||
return x !== ".DS_Store";
|
||||
};
|
||||
|
||||
const presetLocs = [
|
||||
path.join(__dirname, "../../babel-preset-es2015"),
|
||||
path.join(__dirname, "../../babel-preset-react"),
|
||||
].join(",");
|
||||
|
||||
const pluginLocs = [
|
||||
path.join(__dirname, "/../../babel-plugin-transform-strict-mode"),
|
||||
path.join(__dirname, "/../../babel-plugin-transform-es2015-modules-commonjs"),
|
||||
].join(",");
|
||||
|
||||
const readDir = function(loc, filter) {
|
||||
const files = {};
|
||||
if (fs.existsSync(loc)) {
|
||||
readdir(loc, filter).forEach(function(filename) {
|
||||
files[filename] = helper.readFile(path.join(loc, filename));
|
||||
});
|
||||
}
|
||||
return files;
|
||||
};
|
||||
|
||||
const saveInFiles = function(files) {
|
||||
// Place an empty .babelrc in each test so tests won't unexpectedly get to repo-level config.
|
||||
outputFileSync(".babelrc", "{}");
|
||||
|
||||
Object.keys(files).forEach(function(filename) {
|
||||
const content = files[filename];
|
||||
outputFileSync(filename, content);
|
||||
});
|
||||
};
|
||||
|
||||
const assertTest = function(stdout, stderr, opts) {
|
||||
const expectStderr = opts.stderr.trim();
|
||||
stderr = stderr.trim();
|
||||
|
||||
if (opts.stderr) {
|
||||
if (opts.stderrContains) {
|
||||
assert.ok(
|
||||
includes(stderr, expectStderr),
|
||||
"stderr " +
|
||||
JSON.stringify(stderr) +
|
||||
" didn't contain " +
|
||||
JSON.stringify(expectStderr),
|
||||
);
|
||||
} else {
|
||||
chai.expect(stderr).to.equal(expectStderr, "stderr didn't match");
|
||||
}
|
||||
} else if (stderr) {
|
||||
throw new Error("stderr:\n" + stderr);
|
||||
}
|
||||
|
||||
const expectStdout = opts.stdout.trim();
|
||||
stdout = stdout.trim();
|
||||
stdout = stdout.replace(/\\/g, "/");
|
||||
|
||||
if (opts.stdout) {
|
||||
if (opts.stdoutContains) {
|
||||
assert.ok(
|
||||
includes(stdout, expectStdout),
|
||||
"stdout " +
|
||||
JSON.stringify(stdout) +
|
||||
" didn't contain " +
|
||||
JSON.stringify(expectStdout),
|
||||
);
|
||||
} else {
|
||||
chai.expect(stdout).to.equal(expectStdout, "stdout didn't match");
|
||||
}
|
||||
} else if (stdout) {
|
||||
throw new Error("stdout:\n" + stdout);
|
||||
}
|
||||
|
||||
if (opts.outFiles) {
|
||||
const actualFiles = readDir(path.join(tmpLoc));
|
||||
|
||||
Object.keys(actualFiles).forEach(function(filename) {
|
||||
if (!opts.inFiles.hasOwnProperty(filename)) {
|
||||
const expect = opts.outFiles[filename];
|
||||
const actual = actualFiles[filename];
|
||||
|
||||
chai.expect(expect, "Output is missing: " + filename).to.not.be
|
||||
.undefined;
|
||||
|
||||
if (expect) {
|
||||
chai
|
||||
.expect(actual)
|
||||
.to.equal(expect, "Compiled output does not match: " + filename);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Object.keys(opts.outFiles).forEach(function(filename) {
|
||||
chai
|
||||
.expect(actualFiles, "Extraneous file in output: " + filename)
|
||||
.to.contain.key(filename);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const buildTest = function(binName, testName, opts) {
|
||||
const binLoc = path.join(__dirname, "../lib", binName);
|
||||
|
||||
return function(callback) {
|
||||
clear();
|
||||
saveInFiles(opts.inFiles);
|
||||
|
||||
let args = [binLoc];
|
||||
|
||||
args.push("--presets", presetLocs, "--plugins", pluginLocs);
|
||||
args.push("--only", "../../../../packages/*/test");
|
||||
|
||||
args = args.concat(opts.args);
|
||||
|
||||
const spawn = child.spawn(process.execPath, args);
|
||||
|
||||
let stderr = "";
|
||||
let stdout = "";
|
||||
|
||||
spawn.stderr.on("data", function(chunk) {
|
||||
stderr += chunk;
|
||||
});
|
||||
|
||||
spawn.stdout.on("data", function(chunk) {
|
||||
stdout += chunk;
|
||||
});
|
||||
|
||||
spawn.on("close", function() {
|
||||
let err;
|
||||
|
||||
try {
|
||||
assertTest(stdout, stderr, opts);
|
||||
} catch (e) {
|
||||
err = e;
|
||||
}
|
||||
|
||||
if (err) {
|
||||
err.message =
|
||||
args.map(arg => `"${arg}"`).join(" ") + ": " + err.message;
|
||||
}
|
||||
|
||||
callback(err);
|
||||
});
|
||||
|
||||
if (opts.stdin) {
|
||||
spawn.stdin.write(opts.stdin);
|
||||
spawn.stdin.end();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
const clear = function() {
|
||||
process.chdir(__dirname);
|
||||
if (fs.existsSync(tmpLoc)) rimraf.sync(tmpLoc);
|
||||
fs.mkdirSync(tmpLoc);
|
||||
process.chdir(tmpLoc);
|
||||
};
|
||||
|
||||
fs.readdirSync(fixtureLoc).forEach(function(binName) {
|
||||
if (binName[0] === ".") return;
|
||||
|
||||
const suiteLoc = path.join(fixtureLoc, binName);
|
||||
describe("bin/" + binName, function() {
|
||||
fs.readdirSync(suiteLoc).forEach(function(testName) {
|
||||
if (testName[0] === ".") return;
|
||||
|
||||
const testLoc = path.join(suiteLoc, testName);
|
||||
|
||||
const opts = {
|
||||
args: [],
|
||||
};
|
||||
|
||||
const optionsLoc = path.join(testLoc, "options.json");
|
||||
if (fs.existsSync(optionsLoc)) merge(opts, require(optionsLoc));
|
||||
|
||||
["stdout", "stdin", "stderr"].forEach(function(key) {
|
||||
const loc = path.join(testLoc, key + ".txt");
|
||||
if (fs.existsSync(loc)) {
|
||||
opts[key] = helper.readFile(loc);
|
||||
} else {
|
||||
opts[key] = opts[key] || "";
|
||||
}
|
||||
});
|
||||
|
||||
opts.outFiles = readDir(path.join(testLoc, "out-files"), fileFilter);
|
||||
opts.inFiles = readDir(path.join(testLoc, "in-files"), fileFilter);
|
||||
|
||||
const babelrcLoc = path.join(testLoc, ".babelrc");
|
||||
if (fs.existsSync(babelrcLoc)) {
|
||||
// copy .babelrc file to tmp directory
|
||||
opts.inFiles[".babelrc"] = helper.readFile(babelrcLoc);
|
||||
}
|
||||
|
||||
it(testName, buildTest(binName, testName, opts));
|
||||
});
|
||||
});
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user