"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = _default;
exports.runCodeInTestContext = runCodeInTestContext;
var babel = require("@babel/core");
var _helperFixtures = require("@babel/helper-fixtures");
var _codeFrame = require("@babel/code-frame");
var helpers = require("./helpers");
var _assert = require("assert");
var _fs = require("fs");
var _path = require("path");
var _vm = require("vm");
var _quickLru = require("quick-lru");
var _url = require("url");
var _module = require("module");
var _helperCheckDuplicateNodes = require("@babel/helper-check-duplicate-nodes");
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
{
if (!_assert.rejects) {
_assert.rejects = _asyncToGenerator(function* (block, validateError) {
try {
yield typeof block === "function" ? block() : block;
return Promise.reject(new Error("Promise not rejected"));
} catch (error) {
if (typeof validateError === "function" && !validateError(error)) {
return Promise.reject(new Error("Promise rejected with invalid error"));
}
}
});
}
}
const EXTERNAL_HELPERS_VERSION = "7.100.0";
const cachedScripts = new _quickLru({
maxSize: 10
});
const contextModuleCache = new WeakMap();
const sharedTestContext = createContext();
function transformWithoutConfigFile(code, opts) {
return babel.transformSync(code, Object.assign({
configFile: false,
babelrc: false
}, opts));
}
function transformAsyncWithoutConfigFile(code, opts) {
return babel.transformAsync(code, Object.assign({
configFile: false,
babelrc: false
}, opts));
}
function createContext() {
const context = _vm.createContext(Object.assign({}, helpers, {
process: process,
transform: transformWithoutConfigFile,
transformAsync: transformAsyncWithoutConfigFile,
setTimeout: setTimeout,
setImmediate: setImmediate,
expect
}));
context.global = context;
const moduleCache = Object.create(null);
contextModuleCache.set(context, moduleCache);
runCacheableScriptInTestContext(_path.join(_path.dirname(__filename), "babel-helpers-in-memory.js"), babel.buildExternalHelpers, context, moduleCache);
return context;
}
function runCacheableScriptInTestContext(filename, srcFn, context, moduleCache) {
let cached = cachedScripts.get(filename);
if (!cached) {
const code = `(function (exports, require, module, __filename, __dirname) {\n${srcFn()}\n});`;
cached = {
code,
cachedData: undefined
};
cachedScripts.set(filename, cached);
}
let script;
{
script = new _vm.Script(cached.code, {
filename,
lineOffset: -1,
cachedData: cached.cachedData,
produceCachedData: true
});
if (script.cachedDataProduced) {
cached.cachedData = script.cachedData;
}
}
const module = {
id: filename,
exports: {}
};
moduleCache[filename] = module;
const req = id => runModuleInTestContext(id, filename, context, moduleCache);
const dirname = _path.dirname(filename);
script.runInContext(context).call(module.exports, module.exports, req, module, filename, dirname);
return module;
}
function runModuleInTestContext(id, relativeFilename, context, moduleCache) {
const filename = (((v, w) => (v = v.split("."), w = w.split("."), +v[0] > +w[0] || v[0] == w[0] && +v[1] >= +w[1]))(process.versions.node, "8.9") ? require.resolve : (r, {
paths: [b]
}, M = require("module")) => {
let f = M._findPath(r, M._nodeModulePaths(b).concat(b));
if (f) return f;
f = new Error(`Cannot resolve module '${r}'`);
f.code = "MODULE_NOT_FOUND";
throw f;
})(id, {
paths: [_path.dirname(relativeFilename)]
});
if (filename === id) return require(id);
if (moduleCache[filename]) return moduleCache[filename].exports;
return runCacheableScriptInTestContext(filename, () => _fs.readFileSync(filename, "utf8"), context, moduleCache).exports;
}
function runCodeInTestContext(code, opts, context = sharedTestContext) {
const filename = opts.filename;
const dirname = _path.dirname(filename);
const moduleCache = contextModuleCache.get(context);
const req = id => runModuleInTestContext(id, filename, context, moduleCache);
const module = {
id: filename,
exports: {}
};
const oldCwd = process.cwd();
try {
if (opts.filename) process.chdir(_path.dirname(opts.filename));
const src = `(function(exports, require, module, __filename, __dirname, opts) {\n${code}\n});`;
return _vm.runInContext(src, context, {
filename,
displayErrors: true,
lineOffset: -1
})(module.exports, req, module, filename, dirname, opts);
} finally {
process.chdir(oldCwd);
}
}
function maybeMockConsole(_x3, _x4) {
return _maybeMockConsole.apply(this, arguments);
}
function _maybeMockConsole() {
_maybeMockConsole = _asyncToGenerator(function* (validateLogs, run) {
const actualLogs = {
stdout: "",
stderr: ""
};
if (!validateLogs) return {
result: yield run(),
actualLogs
};
const spy1 = jest.spyOn(console, "log").mockImplementation(msg => {
actualLogs.stdout += `${msg}\n`;
});
const spy2 = jest.spyOn(console, "warn").mockImplementation(msg => {
actualLogs.stderr += `${msg}\n`;
});
try {
return {
result: yield run(),
actualLogs
};
} finally {
spy1.mockRestore();
spy2.mockRestore();
}
});
return _maybeMockConsole.apply(this, arguments);
}
function run(_x5) {
return _run.apply(this, arguments);
}
function _run() {
_run = _asyncToGenerator(function* (task) {
const {
actual,
expect: expected,
exec,
options: opts,
doNotSetSourceType,
optionsDir,
validateLogs,
ignoreOutput,
stdout,
stderr
} = task;
function getOpts(self) {
const newOpts = Object.assign({
ast: true,
cwd: _path.dirname(self.loc),
filename: self.loc,
filenameRelative: self.filename,
sourceFileName: self.filename
}, doNotSetSourceType ? {} : {
sourceType: "script"
}, {
babelrc: false,
configFile: false,
inputSourceMap: task.inputSourceMap || undefined
}, opts);
return (0, _helperFixtures.resolveOptionPluginOrPreset)(newOpts, optionsDir);
}
let execCode = exec.code;
let result;
let resultExec;
if (execCode) {
const context = createContext();
const execOpts = getOpts(exec);
({
result
} = yield maybeMockConsole(validateLogs, () => babel.transformAsync(execCode, execOpts)));
(0, _helperCheckDuplicateNodes.default)(result.ast);
execCode = result.code;
try {
resultExec = runCodeInTestContext(execCode, execOpts, context);
} catch (err) {
err.message = `${exec.loc}: ${err.message}\n` + (0, _codeFrame.codeFrameColumns)(execCode, {});
throw err;
}
}
const inputCode = actual.code;
const expectedCode = expected.code;
if (!execCode || inputCode) {
let actualLogs;
({
result,
actualLogs
} = yield maybeMockConsole(validateLogs, () => babel.transformAsync(inputCode, getOpts(actual))));
const outputCode = normalizeOutput(result.code);
(0, _helperCheckDuplicateNodes.default)(result.ast);
if (!ignoreOutput) {
if (!expected.code && outputCode && !opts.throws && _fs.statSync(_path.dirname(expected.loc)).isDirectory() && !process.env.CI) {
const expectedFile = expected.loc.replace(/\.m?js$/, result.sourceType === "module" ? ".mjs" : ".js");
console.log(`New test file created: ${expectedFile}`);
_fs.writeFileSync(expectedFile, `${outputCode}\n`);
if (expected.loc !== expectedFile) {
try {
_fs.unlinkSync(expected.loc);
} catch (e) {}
}
} else {
validateFile(outputCode, expected.loc, expectedCode);
if (inputCode) {
expect(expected.loc).toMatch(result.sourceType === "module" ? /\.mjs$/ : /\.js$/);
}
}
}
if (validateLogs) {
validateFile(normalizeOutput(actualLogs.stdout, true), stdout.loc, stdout.code);
validateFile(normalizeOutput(actualLogs.stderr, true), stderr.loc, stderr.code);
}
}
if (opts.sourceMaps === true) {
try {
expect(result.map).toEqual(task.sourceMap);
} catch (e) {
if (!process.env.OVERWRITE && task.sourceMap) throw e;
console.log(`Updated test file: ${task.sourceMapFile.loc}`);
_fs.writeFileSync(task.sourceMapFile.loc, JSON.stringify(result.map, null, 2));
}
}
if (execCode && resultExec) {
return resultExec;
}
});
return _run.apply(this, arguments);
}
function validateFile(actualCode, expectedLoc, expectedCode) {
try {
expect(actualCode).toEqualFile({
filename: expectedLoc,
code: expectedCode
});
} catch (e) {
if (!process.env.OVERWRITE) throw e;
console.log(`Updated test file: ${expectedLoc}`);
_fs.writeFileSync(expectedLoc, `${actualCode}\n`);
}
}
function escapeRegExp(string) {
return string.replace(/[|\\{}()[\]^$+*?.]/g, "\\$&");
}
function normalizeOutput(code, normalizePathSeparator) {
const projectRoot = _path.resolve(_path.dirname(__filename), "../../../");
const cwdSymbol = "<CWD>";
let result = code.trim().replace(new RegExp(escapeRegExp(projectRoot), "g"), cwdSymbol);
if (process.platform === "win32") {
result = result.replace(new RegExp(escapeRegExp(projectRoot.replace(/\\/g, "/")), "g"), cwdSymbol).replace(new RegExp(escapeRegExp(projectRoot.replace(/\\/g, "\\\\")), "g"), cwdSymbol);
if (normalizePathSeparator) {
result = result.replace(/<CWD>[\w\\/.-]+/g, path => path.replace(/\\\\?/g, "/"));
}
}
return result;
}
expect.extend({
toEqualFile(actual, {
filename,
code
}) {
if (this.isNot) {
throw new Error(".toEqualFile does not support negation");
}
const pass = actual === code;
return {
pass,
message: () => {
const diffString = this.utils.diff(code, actual, {
expand: false
});
return `Expected ${filename} to match transform output.\n` + `To autogenerate a passing version of this file, delete the file and re-run the tests.\n\n` + `Diff:\n\n${diffString}`;
}
};
}
});
function _default(fixturesLoc, name, suiteOpts = {}, taskOpts = {}, dynamicOpts) {
const suites = (0, _helperFixtures.default)(fixturesLoc);
for (const testSuite of suites) {
var _suiteOpts$ignoreSuit;
if ((_suiteOpts$ignoreSuit = suiteOpts.ignoreSuites) != null && _suiteOpts$ignoreSuit.includes(testSuite.title)) continue;
describe(name + "/" + testSuite.title, function () {
for (const task of testSuite.tests) {
var _suiteOpts$ignoreTask, _suiteOpts$ignoreTask2;
if ((_suiteOpts$ignoreTask = suiteOpts.ignoreTasks) != null && _suiteOpts$ignoreTask.includes(task.title) || (_suiteOpts$ignoreTask2 = suiteOpts.ignoreTasks) != null && _suiteOpts$ignoreTask2.includes(testSuite.title + "/" + task.title)) {
continue;
}
const testFn = task.disabled ? it.skip : it;
testFn(task.title, _asyncToGenerator(function* () {
const runTask = () => run(task);
if ("sourceMap" in task.options) {
throw new Error("`sourceMap` option is deprecated. Use `sourceMaps` instead.");
}
if ("sourceMaps" in task.options === false) {
task.options.sourceMaps = !!task.sourceMap;
}
Object.assign(task.options, taskOpts);
if (dynamicOpts) dynamicOpts(task.options, task);
if (task.externalHelpers) {
var _task$options, _task$options$plugins;
((_task$options$plugins = (_task$options = task.options).plugins) != null ? _task$options$plugins : _task$options.plugins = []).push(["external-helpers", {
helperVersion: EXTERNAL_HELPERS_VERSION
}]);
}
const throwMsg = task.options.throws;
if (throwMsg) {
delete task.options.throws;
yield _assert.rejects(runTask, function (err) {
_assert.ok(throwMsg === true || err.message.includes(throwMsg), `
Expected Error: ${throwMsg}
Actual Error: ${err.message}`);
return true;
});
} else {
return runTask();
}
}));
}
});
}
}
//# sourceMappingURL=index.js.map
|