This is much like Babylon's existing behavior around `expected.json`. The equivalent of babel/babylon#188 is already applied here, to guard against silent failure (and a potential false positive) if a test is accidentally committed without its expected.js.
170 lines
4.6 KiB
JavaScript
170 lines
4.6 KiB
JavaScript
import * as babel from "babel-core";
|
|
import { buildExternalHelpers } from "babel-core";
|
|
import getFixtures from "babel-helper-fixtures";
|
|
import sourceMap from "source-map";
|
|
import codeFrame from "babel-code-frame";
|
|
import * as helpers from "./helpers";
|
|
import assert from "assert";
|
|
import chai from "chai";
|
|
import _ from "lodash";
|
|
import "babel-polyfill";
|
|
import fs from "fs";
|
|
import path from "path";
|
|
|
|
let babelHelpers = eval(buildExternalHelpers(null, "var"));
|
|
|
|
function wrapPackagesArray(type, names) {
|
|
return (names || []).map(function (val) {
|
|
if (typeof val === "string") val = [val];
|
|
val[0] = __dirname + "/../../babel-" + type + "-" + val[0];
|
|
return val;
|
|
});
|
|
}
|
|
|
|
function run(task) {
|
|
let actual = task.actual;
|
|
let expect = task.expect;
|
|
let exec = task.exec;
|
|
let opts = task.options;
|
|
|
|
function getOpts(self) {
|
|
let newOpts = _.merge({
|
|
filename: self.loc,
|
|
}, opts);
|
|
|
|
newOpts.plugins = wrapPackagesArray("plugin", newOpts.plugins);
|
|
newOpts.presets = wrapPackagesArray("preset", newOpts.presets).map(function (val) {
|
|
if (val.length > 2) {
|
|
throw new Error(`Unexpected extra options ${JSON.stringify(val.slice(2))} passed to preset.`);
|
|
}
|
|
|
|
return val;
|
|
});
|
|
|
|
return newOpts;
|
|
}
|
|
|
|
let execCode = exec.code;
|
|
let result;
|
|
let resultExec;
|
|
|
|
if (execCode) {
|
|
let execOpts = getOpts(exec);
|
|
result = babel.transform(execCode, execOpts);
|
|
execCode = result.code;
|
|
|
|
try {
|
|
resultExec = runExec(execOpts, execCode);
|
|
} catch (err) {
|
|
err.message = exec.loc + ": " + err.message;
|
|
err.message += codeFrame(execCode);
|
|
throw err;
|
|
}
|
|
}
|
|
|
|
let actualCode = actual.code;
|
|
let expectCode = expect.code;
|
|
if (!execCode || actualCode) {
|
|
result = babel.transform(actualCode, getOpts(actual));
|
|
if (!expect.code && result.code && !opts.throws && fs.statSync(path.dirname(expect.loc)).isDirectory() && !process.env.CI) {
|
|
fs.writeFileSync(expect.loc, result.code);
|
|
} else {
|
|
actualCode = result.code.trim();
|
|
chai.expect(actualCode).to.be.equal(expectCode, actual.loc + " !== " + expect.loc);
|
|
}
|
|
}
|
|
|
|
if (task.sourceMap) {
|
|
chai.expect(result.map).to.deep.equal(task.sourceMap);
|
|
}
|
|
|
|
if (task.sourceMappings) {
|
|
let consumer = new sourceMap.SourceMapConsumer(result.map);
|
|
|
|
_.each(task.sourceMappings, function (mapping) {
|
|
let actual = mapping.original;
|
|
|
|
let expect = consumer.originalPositionFor(mapping.generated);
|
|
chai.expect({ line: expect.line, column: expect.column }).to.deep.equal(actual);
|
|
});
|
|
}
|
|
|
|
if (execCode && resultExec) {
|
|
return resultExec;
|
|
}
|
|
}
|
|
|
|
function runExec(opts, execCode) {
|
|
let sandbox = {
|
|
...helpers,
|
|
babelHelpers,
|
|
assert: chai.assert,
|
|
transform: babel.transform,
|
|
opts,
|
|
exports: {},
|
|
};
|
|
|
|
let fn = new Function(...Object.keys(sandbox), execCode);
|
|
return fn.apply(null, Object.values(sandbox));
|
|
}
|
|
|
|
export default function (
|
|
fixturesLoc: string,
|
|
name: string,
|
|
suiteOpts = {},
|
|
taskOpts = {},
|
|
dynamicOpts?: Function,
|
|
) {
|
|
let suites = getFixtures(fixturesLoc);
|
|
|
|
for (let testSuite of suites) {
|
|
if (_.includes(suiteOpts.ignoreSuites, testSuite.title)) continue;
|
|
|
|
describe(name + "/" + testSuite.title, function () {
|
|
for (let task of testSuite.tests) {
|
|
if (_.includes(suiteOpts.ignoreTasks, task.title) ||
|
|
_.includes(suiteOpts.ignoreTasks, testSuite.title + "/" + task.title)) continue;
|
|
|
|
it(task.title, !task.disabled && function () {
|
|
function runTask() {
|
|
run(task);
|
|
}
|
|
|
|
_.defaults(task.options, {
|
|
filenameRelative: task.expect.filename,
|
|
sourceFileName: task.actual.filename,
|
|
sourceMapTarget: task.expect.filename,
|
|
suppressDeprecationMessages: true,
|
|
babelrc: false,
|
|
sourceMap: !!(task.sourceMappings || task.sourceMap),
|
|
});
|
|
|
|
_.extend(task.options, taskOpts);
|
|
|
|
if (dynamicOpts) dynamicOpts(task.options, task);
|
|
|
|
let throwMsg = task.options.throws;
|
|
if (throwMsg) {
|
|
// internal api doesn't have this option but it's best not to pollute
|
|
// the options object with useless options
|
|
delete task.options.throws;
|
|
|
|
assert.throws(runTask, function (err) {
|
|
return throwMsg === true || err.message.indexOf(throwMsg) >= 0;
|
|
});
|
|
} else {
|
|
if (task.exec.code) {
|
|
let result = run(task);
|
|
if (result && typeof result.then === "function") {
|
|
return result;
|
|
}
|
|
} else {
|
|
runTask();
|
|
}
|
|
}
|
|
});
|
|
}
|
|
});
|
|
}
|
|
}
|