babel/packages/babel-core/test/config-chain.js
2018-03-03 10:58:19 +01:00

959 lines
27 KiB
JavaScript

import assert from "assert";
import fs from "fs";
import path from "path";
import { loadOptions } from "../lib";
function fixture(...args) {
return path.join(__dirname, "fixtures", "config", ...args);
}
describe("buildConfigChain", function() {
describe("test", () => {
describe("single", () => {
it("should process matching string values", () => {
const opts = loadOptions({
filename: fixture("nonexistant-fake", "src.js"),
babelrc: false,
test: fixture("nonexistant-fake"),
comments: true,
});
assert.equal(opts.comments, true);
});
it("should process matching RegExp values", () => {
const opts = loadOptions({
filename: fixture("nonexistant-fake", "src.js"),
babelrc: false,
test: new RegExp(fixture("nonexistant-fake")),
comments: true,
});
assert.equal(opts.comments, true);
});
it("should process matching function values", () => {
const opts = loadOptions({
filename: fixture("nonexistant-fake", "src.js"),
babelrc: false,
test: p => p.indexOf(fixture("nonexistant-fake")) === 0,
comments: true,
});
assert.equal(opts.comments, true);
});
it("should process non-matching string values", () => {
const opts = loadOptions({
filename: fixture("nonexistant-fake", "src.js"),
babelrc: false,
test: fixture("nonexistant-fake-unknown"),
comments: true,
});
assert.equal(opts.comments, undefined);
});
it("should process non-matching RegExp values", () => {
const opts = loadOptions({
filename: fixture("nonexistant-fake", "src.js"),
babelrc: false,
test: new RegExp(fixture("nonexistant-unknown")),
comments: true,
});
assert.equal(opts.comments, undefined);
});
it("should process non-matching function values", () => {
const opts = loadOptions({
filename: fixture("nonexistant-fake", "src.js"),
babelrc: false,
test: p => p.indexOf(fixture("nonexistant-unknown")) === 0,
comments: true,
});
assert.equal(opts.comments, undefined);
});
});
describe("array", () => {
it("should process matching string values", () => {
const opts = loadOptions({
filename: fixture("nonexistant-fake", "src.js"),
babelrc: false,
test: [fixture("nonexistant-fake")],
comments: true,
});
assert.equal(opts.comments, true);
});
it("should process matching RegExp values", () => {
const opts = loadOptions({
filename: fixture("nonexistant-fake", "src.js"),
babelrc: false,
test: [new RegExp(fixture("nonexistant-fake"))],
comments: true,
});
assert.equal(opts.comments, true);
});
it("should process matching function values", () => {
const opts = loadOptions({
filename: fixture("nonexistant-fake", "src.js"),
babelrc: false,
test: [p => p.indexOf(fixture("nonexistant-fake")) === 0],
comments: true,
});
assert.equal(opts.comments, true);
});
it("should process non-matching string values", () => {
const opts = loadOptions({
filename: fixture("nonexistant-fake", "src.js"),
babelrc: false,
test: [fixture("nonexistant-fake-unknown")],
comments: true,
});
assert.equal(opts.comments, undefined);
});
it("should process non-matching RegExp values", () => {
const opts = loadOptions({
filename: fixture("nonexistant-fake", "src.js"),
babelrc: false,
test: [new RegExp(fixture("nonexistant-unknown"))],
comments: true,
});
assert.equal(opts.comments, undefined);
});
it("should process non-matching function values", () => {
const opts = loadOptions({
filename: fixture("nonexistant-fake", "src.js"),
babelrc: false,
test: [p => p.indexOf(fixture("nonexistant-unknown")) === 0],
comments: true,
});
assert.equal(opts.comments, undefined);
});
});
});
describe("include", () => {
describe("single", () => {
it("should process matching string values", () => {
const opts = loadOptions({
filename: fixture("nonexistant-fake", "src.js"),
babelrc: false,
include: fixture("nonexistant-fake"),
comments: true,
});
assert.equal(opts.comments, true);
});
it("should process matching RegExp values", () => {
const opts = loadOptions({
filename: fixture("nonexistant-fake", "src.js"),
babelrc: false,
include: new RegExp(fixture("nonexistant-fake")),
comments: true,
});
assert.equal(opts.comments, true);
});
it("should process matching function values", () => {
const opts = loadOptions({
filename: fixture("nonexistant-fake", "src.js"),
babelrc: false,
include: p => p.indexOf(fixture("nonexistant-fake")) === 0,
comments: true,
});
assert.equal(opts.comments, true);
});
it("should process non-matching string values", () => {
const opts = loadOptions({
filename: fixture("nonexistant-fake", "src.js"),
babelrc: false,
include: fixture("nonexistant-fake-unknown"),
comments: true,
});
assert.equal(opts.comments, undefined);
});
it("should process non-matching RegExp values", () => {
const opts = loadOptions({
filename: fixture("nonexistant-fake", "src.js"),
babelrc: false,
include: new RegExp(fixture("nonexistant-unknown")),
comments: true,
});
assert.equal(opts.comments, undefined);
});
it("should process non-matching function values", () => {
const opts = loadOptions({
filename: fixture("nonexistant-fake", "src.js"),
babelrc: false,
include: p => p.indexOf(fixture("nonexistant-unknown")) === 0,
comments: true,
});
assert.equal(opts.comments, undefined);
});
});
describe("array", () => {
it("should process matching string values", () => {
const opts = loadOptions({
filename: fixture("nonexistant-fake", "src.js"),
babelrc: false,
include: [fixture("nonexistant-fake")],
comments: true,
});
assert.equal(opts.comments, true);
});
it("should process matching RegExp values", () => {
const opts = loadOptions({
filename: fixture("nonexistant-fake", "src.js"),
babelrc: false,
include: [new RegExp(fixture("nonexistant-fake"))],
comments: true,
});
assert.equal(opts.comments, true);
});
it("should process matching function values", () => {
const opts = loadOptions({
filename: fixture("nonexistant-fake", "src.js"),
babelrc: false,
include: [p => p.indexOf(fixture("nonexistant-fake")) === 0],
comments: true,
});
assert.equal(opts.comments, true);
});
it("should process non-matching string values", () => {
const opts = loadOptions({
filename: fixture("nonexistant-fake", "src.js"),
babelrc: false,
include: [fixture("nonexistant-fake-unknown")],
comments: true,
});
assert.equal(opts.comments, undefined);
});
it("should process non-matching RegExp values", () => {
const opts = loadOptions({
filename: fixture("nonexistant-fake", "src.js"),
babelrc: false,
include: [new RegExp(fixture("nonexistant-unknown"))],
comments: true,
});
assert.equal(opts.comments, undefined);
});
it("should process non-matching function values", () => {
const opts = loadOptions({
filename: fixture("nonexistant-fake", "src.js"),
babelrc: false,
include: [p => p.indexOf(fixture("nonexistant-unknown")) === 0],
comments: true,
});
assert.equal(opts.comments, undefined);
});
});
});
describe("exclude", () => {
describe("single", () => {
it("should process matching string values", () => {
const opts = loadOptions({
filename: fixture("nonexistant-fake", "src.js"),
babelrc: false,
exclude: fixture("nonexistant-fake"),
comments: true,
});
assert.equal(opts.comments, undefined);
});
it("should process matching RegExp values", () => {
const opts = loadOptions({
filename: fixture("nonexistant-fake", "src.js"),
babelrc: false,
exclude: new RegExp(fixture("nonexistant-fake")),
comments: true,
});
assert.equal(opts.comments, undefined);
});
it("should process matching function values", () => {
const opts = loadOptions({
filename: fixture("nonexistant-fake", "src.js"),
babelrc: false,
exclude: p => p.indexOf(fixture("nonexistant-fake")) === 0,
comments: true,
});
assert.equal(opts.comments, undefined);
});
it("should process non-matching string values", () => {
const opts = loadOptions({
filename: fixture("nonexistant-fake", "src.js"),
babelrc: false,
exclude: fixture("nonexistant-fake-unknown"),
comments: true,
});
assert.equal(opts.comments, true);
});
it("should process non-matching RegExp values", () => {
const opts = loadOptions({
filename: fixture("nonexistant-fake", "src.js"),
babelrc: false,
exclude: new RegExp(fixture("nonexistant-unknown")),
comments: true,
});
assert.equal(opts.comments, true);
});
it("should process non-matching function values", () => {
const opts = loadOptions({
filename: fixture("nonexistant-fake", "src.js"),
babelrc: false,
exclude: p => p.indexOf(fixture("nonexistant-unknown")) === 0,
comments: true,
});
assert.equal(opts.comments, true);
});
});
describe("array", () => {
it("should process matching string values", () => {
const opts = loadOptions({
filename: fixture("nonexistant-fake", "src.js"),
babelrc: false,
exclude: [fixture("nonexistant-fake")],
comments: true,
});
assert.equal(opts.comments, undefined);
});
it("should process matching RegExp values", () => {
const opts = loadOptions({
filename: fixture("nonexistant-fake", "src.js"),
babelrc: false,
exclude: [new RegExp(fixture("nonexistant-fake"))],
comments: true,
});
assert.equal(opts.comments, undefined);
});
it("should process matching function values", () => {
const opts = loadOptions({
filename: fixture("nonexistant-fake", "src.js"),
babelrc: false,
exclude: [p => p.indexOf(fixture("nonexistant-fake")) === 0],
comments: true,
});
assert.equal(opts.comments, undefined);
});
it("should process non-matching string values", () => {
const opts = loadOptions({
filename: fixture("nonexistant-fake", "src.js"),
babelrc: false,
exclude: [fixture("nonexistant-fake-unknown")],
comments: true,
});
assert.equal(opts.comments, true);
});
it("should process non-matching RegExp values", () => {
const opts = loadOptions({
filename: fixture("nonexistant-fake", "src.js"),
babelrc: false,
exclude: [new RegExp(fixture("nonexistant-unknown"))],
comments: true,
});
assert.equal(opts.comments, true);
});
it("should process non-matching function values", () => {
const opts = loadOptions({
filename: fixture("nonexistant-fake", "src.js"),
babelrc: false,
exclude: [p => p.indexOf(fixture("nonexistant-unknown")) === 0],
comments: true,
});
assert.equal(opts.comments, true);
});
});
});
describe("ignore", () => {
it("should ignore files that match", () => {
const opts = loadOptions({
filename: fixture("nonexistant-fake", "src.js"),
babelrc: false,
ignore: [
fixture("nonexistant-fake", "src.js"),
// We had a regression where multiple ignore patterns broke things, so
// we keep some extra random items in here.
fixture("nonexistant-fake", "other.js"),
fixture("nonexistant-fake", "misc.js"),
],
});
assert.equal(opts, null);
});
it("should not ignore files that don't match", () => {
const opts = loadOptions({
filename: fixture("nonexistant-fake", "src.js"),
babelrc: false,
ignore: [
fixture("nonexistant-fake", "other.js"),
fixture("nonexistant-fake", "misc.js"),
],
});
assert.notEqual(opts, null);
});
});
describe("only", () => {
it("should ignore files that don't match", () => {
const opts = loadOptions({
filename: fixture("nonexistant-fake", "src.js"),
babelrc: false,
only: [
fixture("nonexistant-fake", "other.js"),
fixture("nonexistant-fake", "misc.js"),
],
});
assert.equal(opts, null);
});
it("should not ignore files that match", () => {
const opts = loadOptions({
filename: fixture("nonexistant-fake", "src.js"),
babelrc: false,
only: [
fixture("nonexistant-fake", "src.js"),
fixture("nonexistant-fake", "misc.js"),
],
});
assert.notEqual(opts, null);
});
});
describe("ignore/only", () => {
it("should ignore files that match ignore and don't match only", () => {
const opts = loadOptions({
filename: fixture("nonexistant-fake", "src.js"),
babelrc: false,
ignore: [fixture("nonexistant-fake", "src.js")],
only: [],
});
assert.equal(opts, null);
});
it("should ignore files that match ignore and also only", () => {
const opts = loadOptions({
filename: fixture("nonexistant-fake", "src.js"),
babelrc: false,
ignore: [fixture("nonexistant-fake", "src.js")],
only: [fixture("nonexistant-fake", "src.js")],
});
assert.equal(opts, null);
});
it("should not ignore files that match only and not ignore", () => {
const opts = loadOptions({
filename: fixture("nonexistant-fake", "src.js"),
babelrc: false,
only: [fixture("nonexistant-fake", "src.js")],
});
assert.notEqual(opts, null);
});
it("should not ignore files when no ignore/only are specified", () => {
const opts = loadOptions({
filename: fixture("nonexistant-fake", "src.js"),
babelrc: false,
});
assert.notEqual(opts, null);
});
it("should allow negation of only", () => {
const opts1 = loadOptions({
filename: fixture("nonexistant-fake", "src.js"),
babelrc: false,
only: [
"!" + fixture("nonexistant-fake"),
fixture("nonexistant-fake", "other.js"),
],
});
assert.equal(opts1, null);
const opts2 = loadOptions({
filename: fixture("nonexistant-fake", "src.js"),
babelrc: false,
only: [
"!" + fixture("nonexistant-fake"),
fixture("nonexistant-fake", "src.js"),
],
});
assert.notEqual(opts2, null);
const opts3 = loadOptions({
filename: fixture("nonexistant-fake", "folder", "src.js"),
babelrc: false,
only: [
"!" + fixture("nonexistant-fake"),
fixture("nonexistant-fake", "folder"),
],
});
assert.notEqual(opts3, null);
});
it("should allow negation of ignore", () => {
const opts1 = loadOptions({
filename: fixture("nonexistant-fake", "src.js"),
babelrc: false,
ignore: [
"!" + fixture("nonexistant-fake", "other.js"),
fixture("nonexistant-fake"),
],
});
assert.equal(opts1, null);
// Tests disabled pending https://github.com/babel/babel/issues/6907
// const opts2 = loadOptions({
// filename: fixture("nonexistant-fake", "src.js"),
// babelrc: false,
// ignore: [
// "!" + fixture("nonexistant-fake", "src.js"),
// fixture("nonexistant-fake"),
// ],
// });
// assert.notEqual(opts2, null);
//
// const opts3 = loadOptions({
// filename: fixture("nonexistant-fake", "folder", "src.js"),
// babelrc: false,
// ignore: [
// "!" + fixture("nonexistant-fake", "folder"),
// fixture("nonexistant-fake"),
// ],
// });
// assert.notEqual(opts3, null);
});
});
describe("caching", function() {
describe("programmatic options", function() {
const plugins1 = [() => ({})];
const plugins2 = [() => ({})];
it("should not cache the input options by identity", () => {
const inputOpts = { plugins: plugins1 };
const opts1 = loadOptions(inputOpts);
inputOpts.plugins = plugins2;
const opts2 = loadOptions(inputOpts);
assert.equal(opts1.plugins.length, 1);
assert.equal(opts2.plugins.length, 1);
assert.notEqual(opts1.plugins[0], opts2.plugins[1]);
});
it("should cache the env plugins by identity", () => {
const plugins = [() => ({})];
const opts1 = loadOptions({
envName: "foo",
env: {
foo: {
plugins,
},
},
});
const opts2 = loadOptions({
envName: "foo",
env: {
foo: {
plugins,
},
},
});
assert.equal(opts1.plugins.length, 1);
assert.equal(opts2.plugins.length, 1);
assert.equal(opts1.plugins[0], opts2.plugins[0]);
});
it("should cache the env presets by identity", () => {
const presets = [() => ({ plugins: [() => ({})] })];
const opts1 = loadOptions({
envName: "foo",
env: {
foo: {
presets,
},
},
});
const opts2 = loadOptions({
envName: "foo",
env: {
foo: {
presets,
},
},
});
assert.equal(opts1.plugins.length, 1);
assert.equal(opts2.plugins.length, 1);
assert.equal(opts1.plugins[0], opts2.plugins[0]);
});
it("should cache the plugin options by identity", () => {
const plugins = [() => ({})];
const opts1 = loadOptions({ plugins });
const opts2 = loadOptions({ plugins });
assert.equal(opts1.plugins.length, 1);
assert.equal(opts2.plugins.length, 1);
assert.equal(opts1.plugins[0], opts2.plugins[0]);
});
it("should cache the presets options by identity", () => {
const presets = [() => ({ plugins: [() => ({})] })];
const opts1 = loadOptions({ presets });
const opts2 = loadOptions({ presets });
assert.equal(opts1.plugins.length, 1);
assert.equal(opts2.plugins.length, 1);
assert.strictEqual(opts1.plugins[0], opts2.plugins[0]);
});
it("should not cache the presets options with passPerPreset", () => {
const presets = [() => ({ plugins: [() => ({})] })];
const opts1 = loadOptions({ presets });
const opts2 = loadOptions({ presets, passPerPreset: true });
const opts3 = loadOptions({ presets, passPerPreset: false });
assert.equal(opts1.plugins.length, 1);
assert.equal(opts2.plugins.length, 0);
assert.equal(opts3.plugins.length, 1);
assert.strictEqual(opts1.plugins[0], opts3.plugins[0]);
});
});
describe("config file options", function() {
function touch(filepath) {
const s = fs.statSync(filepath);
fs.utimesSync(
filepath,
s.atime,
s.mtime + Math.random() > 0.5 ? 1 : -1,
);
}
it("should cache package.json files by mtime", () => {
const filename = fixture(
"complex-plugin-config",
"config-identity",
"pkg",
"src.js",
);
const pkgJSON = fixture(
"complex-plugin-config",
"config-identity",
"pkg",
"package.json",
);
const opts1 = loadOptions({ filename });
const opts2 = loadOptions({ filename });
touch(pkgJSON);
const opts3 = loadOptions({ filename });
const opts4 = loadOptions({ filename });
assert.equal(opts1.plugins.length, 1);
assert.equal(opts2.plugins.length, 1);
assert.equal(opts1.plugins[0], opts2.plugins[0]);
assert.equal(opts3.plugins.length, 1);
assert.equal(opts4.plugins.length, 1);
assert.equal(opts3.plugins[0], opts4.plugins[0]);
// Identity changed after touch().
assert.notEqual(opts1.plugins[0], opts3.plugins[0]);
});
it("should cache .babelrc files by mtime", () => {
const filename = fixture(
"complex-plugin-config",
"config-identity",
"babelrc",
"src.js",
);
const babelrcFile = fixture(
"complex-plugin-config",
"config-identity",
"babelrc",
".babelrc",
);
const opts1 = loadOptions({ filename });
const opts2 = loadOptions({ filename });
touch(babelrcFile);
const opts3 = loadOptions({ filename });
const opts4 = loadOptions({ filename });
assert.equal(opts1.plugins.length, 1);
assert.equal(opts2.plugins.length, 1);
assert.equal(opts1.plugins[0], opts2.plugins[0]);
assert.equal(opts3.plugins.length, 1);
assert.equal(opts4.plugins.length, 1);
assert.equal(opts3.plugins[0], opts4.plugins[0]);
// Identity changed after touch().
assert.notEqual(opts1.plugins[0], opts3.plugins[0]);
});
it("should cache .babelrc.js files programmable behavior", () => {
const filename = fixture(
"complex-plugin-config",
"config-identity",
"babelrc-js",
"src.js",
);
const opts1 = loadOptions({ filename });
const opts2 = loadOptions({ filename });
const opts3 = loadOptions({ filename, envName: "new-env" });
const opts4 = loadOptions({ filename, envName: "new-env" });
assert.equal(opts1.plugins.length, 1);
assert.equal(opts2.plugins.length, 1);
assert.equal(opts1.plugins[0], opts2.plugins[0]);
assert.equal(opts3.plugins.length, 1);
assert.equal(opts4.plugins.length, 1);
assert.equal(opts3.plugins[0], opts4.plugins[0]);
// Identity changed with different .env
assert.notEqual(opts1.plugins[0], opts3.plugins[0]);
});
});
});
describe("overrides merging", () => {
it("should apply matching overrides over base configs", () => {
const opts = loadOptions({
filename: fixture("nonexistant-fake", "src.js"),
babelrc: false,
comments: true,
overrides: [
{
test: fixture("nonexistant-fake"),
comments: false,
},
],
});
assert.equal(opts.comments, false);
});
it("should not apply non-matching overrides over base configs", () => {
const opts = loadOptions({
filename: fixture("nonexistant-fake", "src.js"),
babelrc: false,
comments: true,
overrides: [
{
test: fixture("nonexistant-unknown"),
comments: false,
},
],
});
assert.equal(opts.comments, true);
});
});
describe("config files", () => {
const getDefaults = () => ({
babelrc: false,
cwd: process.cwd(),
envName: "development",
passPerPreset: false,
plugins: [],
presets: [],
});
const realEnv = process.env.NODE_ENV;
const realBabelEnv = process.env.BABEL_ENV;
beforeAll(() => {
delete process.env.NODE_ENV;
delete process.env.BABEL_ENV;
});
afterAll(() => {
if (realEnv) {
process.env.NODE_ENV = realEnv;
process.env.NODE_ENV = realBabelEnv;
}
});
it("should load .babelrc", () => {
const filename = fixture("config-files", "babelrc", "src.js");
assert.deepEqual(loadOptions({ filename }), {
...getDefaults(),
filename,
comments: true,
});
});
it("should load .babelrc.js", () => {
const filename = fixture("config-files", "babelrc-js", "src.js");
assert.deepEqual(loadOptions({ filename }), {
...getDefaults(),
filename,
comments: true,
});
});
it("should load package.json#babel", () => {
const filename = fixture("config-files", "pkg", "src.js");
assert.deepEqual(loadOptions({ filename }), {
...getDefaults(),
filename,
comments: true,
});
});
it("should load .babelignore", () => {
const filename = fixture("config-files", "babelignore", "src.js");
assert.deepEqual(loadOptions({ filename }), null);
});
it("should throw if there are both .babelrc and .babelrc.js", () => {
const filename = fixture("config-files", "both-babelrc", "src.js");
assert.throws(
() => loadOptions({ filename }),
/Multiple configuration files found/,
);
});
it("should throw if there are both .babelrc and package.json", () => {
const filename = fixture("config-files", "pkg-babelrc", "src.js");
assert.throws(
() => loadOptions({ filename }),
/Multiple configuration files found/,
);
});
it("should throw if there are both .babelrc.js and package.json", () => {
const filename = fixture("config-files", "pkg-babelrc-js", "src.js");
assert.throws(
() => loadOptions({ filename }),
/Multiple configuration files found/,
);
});
it("should ignore package.json without a 'babel' property", () => {
const filename = fixture("config-files", "pkg-ignored", "src.js");
assert.deepEqual(loadOptions({ filename }), {
...getDefaults(),
filename,
comments: true,
});
});
it("should show helpful errors for .babelrc", () => {
const filename = fixture("config-files", "babelrc-error", "src.js");
assert.throws(
() => loadOptions({ filename }),
/Error while parsing config - /,
);
});
it("should show helpful errors for .babelrc.js", () => {
const filename = fixture("config-files", "babelrc-js-error", "src.js");
assert.throws(() => loadOptions({ filename }), /Babelrc threw an error/);
});
it("should show helpful errors for package.json", () => {
const filename = fixture("config-files", "pkg-error", "src.js");
assert.throws(
() => loadOptions({ filename }),
/Error while parsing JSON - /,
);
});
});
});