babel-plugin-tester
Advanced tools
Comparing version 10.1.0 to 11.0.0-canary.1
@@ -6,37 +6,36 @@ "use strict"; | ||
}); | ||
exports.default = void 0; | ||
var _path = _interopRequireDefault(require("path")); | ||
var _prettier = _interopRequireDefault(require("prettier")); | ||
exports.prettierFormatter = exports.default = void 0; | ||
var _nodePath = _interopRequireDefault(require("node:path")); | ||
var _debug = _interopRequireDefault(require("debug")); | ||
var _prettier = require("prettier"); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; } | ||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } | ||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } | ||
const configByDir = {}; | ||
function getConfig(dir) { | ||
if (!configByDir.hasOwnProperty(dir)) { | ||
configByDir[dir] = _prettier.default.resolveConfig.sync(dir); | ||
const debug = (0, _debug.default)('babel-plugin-tester:formatter'); | ||
const configDirectoryCache = Object.create(null); | ||
const getCachedConfig = directory => { | ||
if (!(directory in configDirectoryCache)) { | ||
debug(`caching prettier configuration resolved from ${directory}: %O`, configDirectoryCache[directory]); | ||
configDirectoryCache[directory] = _prettier.resolveConfig.sync(directory); | ||
} else { | ||
debug(`using cached prettier configuration resolved from ${directory}`); | ||
} | ||
return configByDir[dir]; | ||
} | ||
function prettierFormatter(code, { | ||
return configDirectoryCache[directory]; | ||
}; | ||
const prettierFormatter = (code, { | ||
cwd = process.cwd(), | ||
filename = _path.default.join(cwd, 'macro-test.js'), | ||
config = getConfig(cwd) | ||
} = {}) { | ||
return _prettier.default.format(code, _objectSpread({ | ||
filepath: filename | ||
}, config)); | ||
} | ||
filename, | ||
filepath = filename || _nodePath.default.join(cwd, 'dummy.js'), | ||
prettierOptions = getCachedConfig(cwd) | ||
} = {}) => { | ||
debug('cwd: %O', cwd); | ||
debug('filepath: %O', filepath); | ||
debug('original code: %O', code); | ||
const formattedCode = (0, _prettier.format)(code, { | ||
filepath, | ||
...prettierOptions | ||
}); | ||
debug('formatted code: %O', code); | ||
return formattedCode; | ||
}; | ||
exports.prettierFormatter = prettierFormatter; | ||
var _default = prettierFormatter; | ||
exports.default = _default; |
@@ -6,42 +6,71 @@ "use strict"; | ||
}); | ||
var _exportNames = { | ||
pluginTester: true, | ||
prettierFormatter: true, | ||
unstringSnapshotSerializer: true, | ||
runPluginUnderTestHere: true, | ||
runPresetUnderTestHere: true | ||
}; | ||
exports.pluginTester = exports.default = defaultPluginTester; | ||
Object.defineProperty(exports, "prettierFormatter", { | ||
enumerable: true, | ||
get: function () { | ||
return _prettier.default; | ||
return _prettier.prettierFormatter; | ||
} | ||
}); | ||
Object.defineProperty(exports, "runPluginUnderTestHere", { | ||
enumerable: true, | ||
get: function () { | ||
return _pluginTester.runPluginUnderTestHere; | ||
} | ||
}); | ||
Object.defineProperty(exports, "runPresetUnderTestHere", { | ||
enumerable: true, | ||
get: function () { | ||
return _pluginTester.runPresetUnderTestHere; | ||
} | ||
}); | ||
Object.defineProperty(exports, "unstringSnapshotSerializer", { | ||
enumerable: true, | ||
get: function () { | ||
return _unstringSnapshotSerializer.default; | ||
return _unstringSnapshot.unstringSnapshotSerializer; | ||
} | ||
}); | ||
exports.default = void 0; | ||
var _pluginTester = _interopRequireDefault(require("./plugin-tester")); | ||
var _prettier = _interopRequireDefault(require("./formatters/prettier")); | ||
var _unstringSnapshotSerializer = _interopRequireDefault(require("./unstring-snapshot-serializer")); | ||
var _debug = _interopRequireDefault(require("debug")); | ||
var _prettier = require("./formatters/prettier"); | ||
var _unstringSnapshot = require("./serializers/unstring-snapshot"); | ||
var _pluginTester = require("./plugin-tester"); | ||
var _types = require("./types"); | ||
Object.keys(_types).forEach(function (key) { | ||
if (key === "default" || key === "__esModule") return; | ||
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return; | ||
if (key in exports && exports[key] === _types[key]) return; | ||
Object.defineProperty(exports, key, { | ||
enumerable: true, | ||
get: function () { | ||
return _types[key]; | ||
} | ||
}); | ||
}); | ||
var _expect; | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; } | ||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } | ||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } | ||
// istanbul ignore else (it's not worth testing) | ||
if (typeof expect !== 'undefined' && expect.addSnapshotSerializer) { | ||
expect.addSnapshotSerializer(_unstringSnapshotSerializer.default); | ||
const debug = (0, _debug.default)('babel-plugin-tester:index'); | ||
if ('expect' in globalThis && typeof ((_expect = expect) === null || _expect === void 0 ? void 0 : _expect.addSnapshotSerializer) == 'function') { | ||
debug('added unstring snapshot serializer globally; all snapshots after this point will be affected'); | ||
expect.addSnapshotSerializer(_unstringSnapshot.unstringSnapshotSerializer); | ||
} else { | ||
debug('unable to add unstring snapshot serializer: global expect object is missing or unsupported'); | ||
} | ||
function defaultPluginTester(options) { | ||
return (0, _pluginTester.default)(_objectSpread({ | ||
formatResult: _prettier.default | ||
}, options)); | ||
return (0, _pluginTester.pluginTester)({ | ||
formatResult: _prettier.prettierFormatter, | ||
...options | ||
}); | ||
} | ||
var _default = defaultPluginTester; | ||
exports.default = _default; | ||
defaultPluginTester.default = defaultPluginTester; | ||
defaultPluginTester.pluginTester = defaultPluginTester; | ||
defaultPluginTester.prettierFormatter = _prettier.prettierFormatter; | ||
defaultPluginTester.unstringSnapshotSerializer = _unstringSnapshot.unstringSnapshotSerializer; | ||
defaultPluginTester.runPluginUnderTestHere = _pluginTester.runPluginUnderTestHere; | ||
defaultPluginTester.runPresetUnderTestHere = _pluginTester.runPresetUnderTestHere; | ||
module.exports = defaultPluginTester; |
@@ -6,261 +6,1034 @@ "use strict"; | ||
}); | ||
exports.default = void 0; | ||
var _assert = _interopRequireDefault(require("assert")); | ||
var _path = _interopRequireDefault(require("path")); | ||
var _fs = _interopRequireDefault(require("fs")); | ||
var _os = require("os"); | ||
var _exportNames = { | ||
pluginTester: true, | ||
restartTestTitleNumbering: true, | ||
runPluginUnderTestHere: true, | ||
runPresetUnderTestHere: true, | ||
validTitleNumberingValues: true, | ||
validEndOfLineValues: true, | ||
prettierFormatter: true, | ||
unstringSnapshotSerializer: true | ||
}; | ||
exports.pluginTester = exports.default = pluginTester; | ||
Object.defineProperty(exports, "prettierFormatter", { | ||
enumerable: true, | ||
get: function () { | ||
return _prettier.prettierFormatter; | ||
} | ||
}); | ||
exports.restartTestTitleNumbering = restartTestTitleNumbering; | ||
exports.runPresetUnderTestHere = exports.runPluginUnderTestHere = void 0; | ||
Object.defineProperty(exports, "unstringSnapshotSerializer", { | ||
enumerable: true, | ||
get: function () { | ||
return _unstringSnapshot.unstringSnapshotSerializer; | ||
} | ||
}); | ||
exports.validTitleNumberingValues = exports.validEndOfLineValues = void 0; | ||
var _nodeAssert = _interopRequireDefault(require("node:assert")); | ||
var _nodePath = _interopRequireDefault(require("node:path")); | ||
var _nodeFs = _interopRequireDefault(require("node:fs")); | ||
var _nodeOs = require("node:os"); | ||
var _types = require("node:util/types"); | ||
var _lodash = _interopRequireDefault(require("lodash.mergewith")); | ||
var _stripIndent = _interopRequireDefault(require("strip-indent")); | ||
const _excluded = ["babel", "plugin", "pluginName", "title", "pluginOptions", "tests", "fixtures", "fixtureOutputName", "filename", "endOfLine"], | ||
_excluded2 = ["plugin", "pluginOptions", "fixtureOutputName", "babel", "endOfLine", "formatResult"], | ||
_excluded3 = ["title", "fixtures", "filename"]; | ||
var _nodeVm = require("node:vm"); | ||
var _debug = _interopRequireDefault(require("debug")); | ||
var _symbols = require("./symbols"); | ||
var _errors = require("./errors"); | ||
var _prettier = require("./formatters/prettier"); | ||
var _unstringSnapshot = require("./serializers/unstring-snapshot"); | ||
var _types2 = require("./types"); | ||
Object.keys(_types2).forEach(function (key) { | ||
if (key === "default" || key === "__esModule") return; | ||
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return; | ||
if (key in exports && exports[key] === _types2[key]) return; | ||
Object.defineProperty(exports, key, { | ||
enumerable: true, | ||
get: function () { | ||
return _types2[key]; | ||
} | ||
}); | ||
}); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
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); }); }; } | ||
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; } | ||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } | ||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } | ||
function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; } | ||
function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; } | ||
const noop = () => {}; // thanks to node throwing an error if you try to use instanceof with an arrow | ||
// function we have to have this function. I guess it's spec... SMH... | ||
// NOTE: I tried doing the "proper thing" using Symbol.hasInstance | ||
// but no matter what that did, I couldn't make that work with a SyntaxError | ||
// because SyntaxError[Symbol.hasInstance]() returns false. What. The. Heck!? | ||
// So I'm doing this .prototype stuff :-/ | ||
function instanceOf(inst, cls) { | ||
return cls.prototype !== undefined && inst instanceof cls; | ||
const parseErrorStackRegExp = /at (?:(?<fn>\S+) )?(?:.*? )?\(?(?<path>(?:\/|file:|\w:\\).*?)(?:\)|$)/i; | ||
const parseScriptFilepathRegExp = /(\/|\\)babel-plugin-tester(\/|\\)(dist|src)(\/|\\)(index|plugin-tester)\.(j|t)s$/; | ||
const isIntegerRegExp = /^\d+$/; | ||
const isIntegerRangeRegExp = /^(?<startStr>\d+)-(?<endStr>\d+)$/; | ||
const noop = () => undefined; | ||
Object.freeze(noop); | ||
const getDebuggers = (namespace, parentDebugger) => { | ||
const debug = parentDebugger.extend(namespace); | ||
return { | ||
debug, | ||
verbose: debug.extend('verbose') | ||
}; | ||
}; | ||
const { | ||
debug: debug1, | ||
verbose: verbose1 | ||
} = getDebuggers('tester', (0, _debug.default)('babel-plugin-tester')); | ||
const runPluginUnderTestHere = Symbol('run-plugin-under-test-here'); | ||
exports.runPluginUnderTestHere = runPluginUnderTestHere; | ||
const runPresetUnderTestHere = Symbol('run-preset-under-test-here'); | ||
exports.runPresetUnderTestHere = runPresetUnderTestHere; | ||
const validTitleNumberingValues = ['all', 'tests-only', 'fixtures-only', false]; | ||
exports.validTitleNumberingValues = validTitleNumberingValues; | ||
const validEndOfLineValues = ['lf', 'crlf', 'auto', 'preserve', false]; | ||
exports.validEndOfLineValues = validEndOfLineValues; | ||
let currentTestNumber = 1; | ||
function restartTestTitleNumbering() { | ||
debug1('restarted title numbering'); | ||
currentTestNumber = 1; | ||
} | ||
const fullDefaultConfig = { | ||
babelOptions: { | ||
parserOpts: {}, | ||
generatorOpts: {}, | ||
babelrc: false, | ||
configFile: false | ||
function pluginTester(options = {}) { | ||
debug1('executing main babel-plugin-tester function'); | ||
const globalContextHasExpectFn = 'expect' in globalThis && typeof expect == 'function'; | ||
const globalContextHasTestFn = 'it' in globalThis && typeof it == 'function'; | ||
const globalContextHasDescribeFn = 'describe' in globalThis && typeof describe == 'function'; | ||
const globalContextExpectFnHasToMatchSnapshot = (() => { | ||
try { | ||
var _expect; | ||
return globalContextHasExpectFn ? typeof ((_expect = expect(undefined)) === null || _expect === void 0 ? void 0 : _expect.toMatchSnapshot) == 'function' : false; | ||
} catch { | ||
return false; | ||
} | ||
})(); | ||
const globalContextTestFnHasSkip = globalContextHasTestFn ? typeof it.skip == 'function' : false; | ||
const globalContextTestFnHasOnly = globalContextHasTestFn ? typeof it.only == 'function' : false; | ||
if (!globalContextHasDescribeFn) { | ||
throw new TypeError(_errors.ErrorMessage.TestEnvironmentUndefinedDescribe()); | ||
} | ||
}; | ||
function mergeCustomizer(objValue, srcValue) { | ||
if (Array.isArray(objValue)) { | ||
return objValue.concat(srcValue); | ||
if (!globalContextHasTestFn) { | ||
throw new TypeError(_errors.ErrorMessage.TestEnvironmentUndefinedIt()); | ||
} | ||
return undefined; | ||
} | ||
function pluginTester(_ref = {}) { | ||
let { | ||
/* istanbul ignore next (TODO: write a test for this) */ | ||
babel = require('@babel/core'), | ||
plugin = requiredParam('plugin'), | ||
pluginName = 'unknown plugin', | ||
title: describeBlockTitle = pluginName, | ||
pluginOptions, | ||
tests, | ||
fixtures, | ||
fixtureOutputName = 'output', | ||
filename, | ||
endOfLine = 'lf' | ||
} = _ref, | ||
rest = _objectWithoutProperties(_ref, _excluded); | ||
let testNumber = 1; | ||
if (fixtures) { | ||
testFixtures(_objectSpread({ | ||
plugin, | ||
pluginName, | ||
pluginOptions, | ||
title: describeBlockTitle, | ||
fixtures, | ||
fixtureOutputName, | ||
filename, | ||
babel, | ||
endOfLine | ||
}, rest)); | ||
} | ||
const testAsArray = toTestArray(tests); | ||
if (!testAsArray.length) { | ||
debug1('global context check succeeded'); | ||
let hasTests = false; | ||
const baseConfig = resolveBaseConfig(); | ||
const envConfig = resolveConfigFromEnvironmentVariables(); | ||
const normalizedTests = normalizeTests(); | ||
verbose1('base configuration: %O', baseConfig); | ||
verbose1('environment-derived config: %O', envConfig); | ||
verbose1('normalized test blocks: %O', normalizedTests); | ||
if (!hasTests) { | ||
debug1('terminated early: no valid tests provided'); | ||
return; | ||
} | ||
const testerConfig = (0, _lodash.default)({}, fullDefaultConfig, rest, mergeCustomizer); | ||
describe(describeBlockTitle, () => { | ||
testAsArray.forEach(testConfig => { | ||
if (!testConfig) { | ||
registerTestsWithTestingFramework(normalizedTests); | ||
debug1('finished registering all test blocks with testing framework'); | ||
debug1('finished executing main babel-plugin-tester function'); | ||
function resolveBaseConfig() { | ||
const { | ||
debug: debug2, | ||
verbose: verbose2 | ||
} = getDebuggers('resolve-base', debug1); | ||
debug2('resolving base configuration'); | ||
const rawBaseConfig = (0, _lodash.default)({ | ||
babelOptions: { | ||
parserOpts: {}, | ||
generatorOpts: {}, | ||
babelrc: false, | ||
configFile: false | ||
}, | ||
titleNumbering: 'all', | ||
endOfLine: 'lf', | ||
formatResult: r => r, | ||
snapshot: false, | ||
fixtureOutputName: 'output', | ||
setup: noop, | ||
teardown: noop | ||
}, options, mergeCustomizer); | ||
verbose2('raw base configuration: %O', rawBaseConfig); | ||
if (rawBaseConfig.plugin && (rawBaseConfig.preset || rawBaseConfig.presetName || rawBaseConfig.presetOptions) || rawBaseConfig.preset && (rawBaseConfig.plugin || rawBaseConfig.pluginName || rawBaseConfig.pluginOptions)) { | ||
throw new TypeError(_errors.ErrorMessage.BadConfigPluginAndPreset()); | ||
} | ||
if (!validTitleNumberingValues.includes(rawBaseConfig.titleNumbering)) { | ||
throw new TypeError(_errors.ErrorMessage.BadConfigInvalidTitleNumbering()); | ||
} | ||
const baseConfig = { | ||
babel: rawBaseConfig.babel || require('@babel/core'), | ||
baseBabelOptions: rawBaseConfig.babelOptions, | ||
titleNumbering: rawBaseConfig.titleNumbering, | ||
filepath: rawBaseConfig.filepath || rawBaseConfig.filename || tryInferFilepath(), | ||
endOfLine: rawBaseConfig.endOfLine, | ||
baseSetup: rawBaseConfig.setup, | ||
baseTeardown: rawBaseConfig.teardown, | ||
baseFormatResult: rawBaseConfig.formatResult, | ||
baseSnapshot: rawBaseConfig.snapshot, | ||
baseFixtureOutputName: rawBaseConfig.fixtureOutputName, | ||
baseFixtureOutputExt: rawBaseConfig.fixtureOutputExt, | ||
fixtures: rawBaseConfig.fixtures, | ||
tests: rawBaseConfig.tests || [] | ||
}; | ||
verbose2('partially constructed base configuration: %O', baseConfig); | ||
if (baseConfig.fixtures !== undefined && typeof baseConfig.fixtures != 'string') { | ||
throw new TypeError(_errors.ErrorMessage.BadConfigFixturesNotString()); | ||
} | ||
if (baseConfig.tests !== undefined && !Array.isArray(baseConfig.tests) && (!baseConfig.tests || typeof baseConfig.tests != 'object')) { | ||
throw new TypeError(_errors.ErrorMessage.BadConfigInvalidTestsType()); | ||
} | ||
baseConfig.tests = Array.isArray(baseConfig.tests) ? baseConfig.tests.filter((test, ndx) => { | ||
if (Array.isArray(test) || typeof test != 'string' && test !== null && test !== undefined && typeof test != 'object') { | ||
throw new TypeError(_errors.ErrorMessage.BadConfigInvalidTestsArrayItemType(ndx)); | ||
} | ||
const result = typeof test == 'string' || Boolean(test); | ||
if (!result) { | ||
debug2(`test item \`%O\` at index ${ndx} was skipped`, test); | ||
} | ||
return result; | ||
}) : Object.fromEntries(Object.entries(baseConfig.tests).filter(([title, test]) => { | ||
if (Array.isArray(test) || typeof test != 'string' && test !== null && test !== undefined && typeof test != 'object') { | ||
throw new TypeError(_errors.ErrorMessage.BadConfigInvalidTestsObjectProperty(title)); | ||
} | ||
const result = typeof test == 'string' || Boolean(test); | ||
if (!result) { | ||
debug2(`test property "${title}" with value \`%O\` was skipped`, test); | ||
} | ||
return result; | ||
})); | ||
if (rawBaseConfig.plugin) { | ||
debug2('running in plugin mode'); | ||
baseConfig.plugin = rawBaseConfig.plugin; | ||
baseConfig.pluginName = rawBaseConfig.pluginName || tryInferPluginName() || 'unknown plugin'; | ||
baseConfig.basePluginOptions = rawBaseConfig.pluginOptions || {}; | ||
} else if (rawBaseConfig.preset) { | ||
debug2('running in preset mode'); | ||
baseConfig.preset = rawBaseConfig.preset; | ||
baseConfig.presetName = rawBaseConfig.presetName || 'unknown preset'; | ||
baseConfig.basePresetOptions = rawBaseConfig.presetOptions; | ||
} else { | ||
throw new TypeError(_errors.ErrorMessage.BadConfigNoPluginOrPreset()); | ||
} | ||
baseConfig.describeBlockTitle = rawBaseConfig.title === false ? false : rawBaseConfig.title || baseConfig.pluginName || baseConfig.presetName || undefined; | ||
debug2('describe block title: %O', baseConfig.describeBlockTitle); | ||
if (rawBaseConfig.restartTitleNumbering) { | ||
restartTestTitleNumbering(); | ||
} | ||
return baseConfig; | ||
function tryInferPluginName() { | ||
debug2('attempting to infer plugin name'); | ||
try { | ||
const { | ||
name | ||
} = rawBaseConfig.plugin({ | ||
assertVersion: noop, | ||
targets: noop, | ||
assumption: noop | ||
}, {}, process.cwd()); | ||
debug2('plugin name inference result: %O', name); | ||
return name; | ||
} catch { | ||
debug2('plugin name inference failed'); | ||
return undefined; | ||
} | ||
} | ||
function tryInferFilepath() { | ||
if ('filepath' in rawBaseConfig || 'filename' in rawBaseConfig) { | ||
debug2('filepath was manually unset'); | ||
return undefined; | ||
} | ||
debug2('attempting to infer filepath'); | ||
const oldStackTraceLimit = Error.stackTraceLimit; | ||
Error.stackTraceLimit = Number.POSITIVE_INFINITY; | ||
try { | ||
var _Error$stack; | ||
let inferredFilepath = undefined; | ||
const reversedCallStack = (((_Error$stack = new Error('faux error').stack) === null || _Error$stack === void 0 ? void 0 : _Error$stack.split('\n').map(line => { | ||
var _line$match; | ||
const { | ||
fn: functionName, | ||
path: filePath | ||
} = ((_line$match = line.match(parseErrorStackRegExp)) === null || _line$match === void 0 ? void 0 : _line$match.groups) || {}; | ||
return filePath ? { | ||
functionName, | ||
filePath: filePath.split(`file://${process.platform == 'win32' ? '/' : ''}`).at(-1).split(':').slice(0, -2).join(':') | ||
} : undefined; | ||
}).filter(o => Boolean(o))) || []).reverse(); | ||
verbose2('reversed call stack: %O', reversedCallStack); | ||
if (reversedCallStack !== null && reversedCallStack !== void 0 && reversedCallStack.length) { | ||
const referenceIndex = findReferenceStackIndex(reversedCallStack); | ||
verbose2('reference index: %O', referenceIndex); | ||
if (referenceIndex) { | ||
var _reversedCallStack$at; | ||
inferredFilepath = (_reversedCallStack$at = reversedCallStack.at(referenceIndex - 1)) === null || _reversedCallStack$at === void 0 ? void 0 : _reversedCallStack$at.filePath; | ||
} | ||
} | ||
debug2('inferred filepath: %O', inferredFilepath); | ||
return inferredFilepath; | ||
} finally { | ||
Error.stackTraceLimit = oldStackTraceLimit; | ||
} | ||
function findReferenceStackIndex(reversedCallStack) { | ||
return [reversedCallStack.findIndex(({ | ||
functionName, | ||
filePath | ||
}) => { | ||
return functionName == 'defaultPluginTester' && parseScriptFilepathRegExp.test(filePath); | ||
}), reversedCallStack.findIndex(({ | ||
functionName, | ||
filePath | ||
}) => { | ||
return functionName == 'pluginTester' && parseScriptFilepathRegExp.test(filePath); | ||
}), reversedCallStack.findIndex(({ | ||
functionName, | ||
filePath | ||
}) => { | ||
return functionName == 'resolveBaseConfig' && parseScriptFilepathRegExp.test(filePath); | ||
})].find(ndx => ndx != -1); | ||
} | ||
} | ||
} | ||
function resolveConfigFromEnvironmentVariables() { | ||
const { | ||
debug: debug2 | ||
} = getDebuggers('resolve-env', debug1); | ||
debug2('resolving environment variable configuration'); | ||
return { | ||
skipTestsByRegExp: stringToRegExp(process.env.TEST_SKIP), | ||
onlyTestsByRegExp: stringToRegExp(process.env.TEST_ONLY), | ||
skipTestsByRange: stringToRanges('TEST_NUM_SKIP', process.env.TEST_NUM_SKIP), | ||
onlyTestsByRange: stringToRanges('TEST_NUM_ONLY', process.env.TEST_NUM_ONLY) | ||
}; | ||
function stringToRegExp(str) { | ||
return str === undefined ? undefined : new RegExp(str, 'u'); | ||
} | ||
function stringToRanges(name, str) { | ||
if (typeof str != 'string') { | ||
return []; | ||
} | ||
return str.split(',').map(s => { | ||
s = s.trim(); | ||
if (s) { | ||
var _s$match; | ||
if (isIntegerRegExp.test(s)) { | ||
return Number(s); | ||
} | ||
const { | ||
startStr, | ||
endStr | ||
} = ((_s$match = s.match(isIntegerRangeRegExp)) === null || _s$match === void 0 ? void 0 : _s$match.groups) || {}; | ||
if (startStr && endStr) { | ||
const start = Number(startStr); | ||
const end = Number(endStr); | ||
const range = { | ||
start, | ||
end | ||
}; | ||
if (start > end) { | ||
throw new TypeError(_errors.ErrorMessage.BadEnvironmentVariableRange(name, s, range)); | ||
} else if (start == end) { | ||
return start; | ||
} | ||
return range; | ||
} | ||
throw new TypeError(_errors.ErrorMessage.BadEnvironmentVariableRange(name, s)); | ||
} | ||
}).filter(s => Boolean(s)); | ||
} | ||
} | ||
function normalizeTests() { | ||
const { | ||
debug: debug2 | ||
} = getDebuggers('normalize', debug1); | ||
debug2('normalizing test items into test objects'); | ||
const { | ||
describeBlockTitle, | ||
filepath, | ||
tests, | ||
fixtures | ||
} = baseConfig; | ||
const testsIsArray = Array.isArray(tests); | ||
const fixturesAbsolutePath = getAbsolutePathUsingFilepathDirname(filepath, fixtures); | ||
const testConfigs = []; | ||
const useFixtureTitleNumbering = baseConfig.titleNumbering == 'all' || baseConfig.titleNumbering == 'fixtures-only'; | ||
const useTestObjectTitleNumbering = baseConfig.titleNumbering == 'all' || baseConfig.titleNumbering == 'tests-only'; | ||
if (fixturesAbsolutePath) { | ||
debug2('potentially generating test objects from fixtures path: %O', fixturesAbsolutePath); | ||
if (_nodeFs.default.statSync(fixturesAbsolutePath).isDirectory()) { | ||
debug2('generating test objects from fixtures path'); | ||
const describeBlock = typeof describeBlockTitle == 'string' ? createAndPushDescribeConfig(`${describeBlockTitle} fixtures`) : undefined; | ||
if (describeBlock === undefined) { | ||
debug2('skipped creating describe block'); | ||
} | ||
createAndPushFixtureConfigs({ | ||
fixturesDirectory: fixturesAbsolutePath, | ||
parentDescribeConfig: describeBlock | ||
}); | ||
} else { | ||
debug2('not generating test objects from fixtures path: path is not a directory'); | ||
} | ||
} else if (typeof fixtures == 'string') { | ||
throw new TypeError(_errors.ErrorMessage.UnableToDeriveAbsolutePath(filepath, '`filepath`', fixtures, '`fixtures`')); | ||
} else { | ||
debug2('skipped loading fixtures: no fixtures path provided'); | ||
} | ||
if (tests && (!testsIsArray || tests.length)) { | ||
debug2('generating test objects from tests'); | ||
const describeBlock = typeof describeBlockTitle == 'string' ? createAndPushDescribeConfig(describeBlockTitle) : undefined; | ||
if (describeBlock === undefined) { | ||
debug2('skipped creating describe block'); | ||
} | ||
if (testsIsArray) { | ||
debug2(`${tests.length} tests were provided via an array`); | ||
((describeBlock === null || describeBlock === void 0 ? void 0 : describeBlock.tests) || testConfigs).push(...tests.map(test => createTestConfig(test))); | ||
} else { | ||
const entries = Object.entries(tests); | ||
debug2(`${entries.length} tests were provided via an object`); | ||
((describeBlock === null || describeBlock === void 0 ? void 0 : describeBlock.tests) || testConfigs).push(...entries.map(([title, test]) => { | ||
return createTestConfig({ | ||
title, | ||
...(typeof test == 'string' ? { | ||
code: test | ||
} : test) | ||
}); | ||
})); | ||
} | ||
} else { | ||
debug2('skipped loading test objects from tests: no tests object or array provided'); | ||
} | ||
debug2('finished normalizing tests'); | ||
return testConfigs; | ||
function createAndPushDescribeConfig(describeBlockTitle, parentDescribeConfig) { | ||
const { | ||
debug: debug3 | ||
} = getDebuggers('create-desc', debug2); | ||
debug3('generating new describe block: %O', describeBlockTitle); | ||
const describeConfig = { | ||
[_symbols.$type]: 'describe-block', | ||
describeBlockTitle, | ||
tests: [] | ||
}; | ||
((parentDescribeConfig === null || parentDescribeConfig === void 0 ? void 0 : parentDescribeConfig.tests) || testConfigs).push(describeConfig); | ||
return describeConfig; | ||
} | ||
function createAndPushFixtureConfigs({ | ||
fixturesDirectory, | ||
fixtureOptions = {}, | ||
parentDescribeConfig | ||
}) { | ||
const { | ||
debug: debug3, | ||
verbose: verbose3 | ||
} = getDebuggers('create-fix', debug2); | ||
debug3('potentially generating test objects from fixture at path %O', fixturesDirectory); | ||
if (!_nodeFs.default.statSync(fixturesDirectory).isDirectory()) { | ||
debug3('test objects generation skipped: path is not a directory'); | ||
return; | ||
} | ||
const rootOptions = (0, _lodash.default)({ | ||
setup: noop, | ||
teardown: noop | ||
}, fixtureOptions, readFixtureOptions(fixturesDirectory), mergeCustomizer); | ||
verbose3('root options: %O', rootOptions); | ||
_nodeFs.default.readdirSync(fixturesDirectory).forEach(filename => { | ||
const fixtureSubdir = _nodePath.default.join(fixturesDirectory, filename); | ||
debug3('potentially generating new test object from fixture at subpath %O', fixtureSubdir); | ||
if (!_nodeFs.default.statSync(fixtureSubdir).isDirectory()) { | ||
debug3('test object generation skipped: subpath is not a directory'); | ||
return; | ||
} | ||
const blockTitle = filename.split('-').join(' '); | ||
const localOptions = (0, _lodash.default)({}, rootOptions, readFixtureOptions(fixtureSubdir), mergeCustomizer); | ||
verbose3('localOptions: %O', localOptions); | ||
const directoryFiles = _nodeFs.default.readdirSync(fixtureSubdir, { | ||
withFileTypes: true | ||
}).filter(file => file.isFile()); | ||
const { | ||
name: codeFilename | ||
} = directoryFiles.find(file => { | ||
return file.name.startsWith('code.'); | ||
}) || {}; | ||
const { | ||
name: execFilename | ||
} = directoryFiles.find(file => { | ||
return file.name.startsWith('exec.'); | ||
}) || {}; | ||
verbose3('code filename: %O', codeFilename); | ||
verbose3('exec filename: %O', execFilename); | ||
if (!codeFilename && !execFilename) { | ||
debug3('no code or exec file found in subpath. Skipped generating test object. Subpath will be scanned for nested fixtures'); | ||
createAndPushFixtureConfigs({ | ||
fixturesDirectory: fixtureSubdir, | ||
fixtureOptions: localOptions, | ||
parentDescribeConfig: createAndPushDescribeConfig(blockTitle, parentDescribeConfig) | ||
}); | ||
} else { | ||
debug3('code or exec file found in subpath. Skipped scanning for nested fixtures. Test object will be generated'); | ||
const codePath = codeFilename ? _nodePath.default.join(fixtureSubdir, codeFilename) : undefined; | ||
const execPath = execFilename ? _nodePath.default.join(fixtureSubdir, execFilename) : undefined; | ||
const hasBabelrc = ['.babelrc', '.babelrc.json', '.babelrc.js', '.babelrc.cjs', '.babelrc.mjs'].some(p => { | ||
return _nodeFs.default.existsSync(_nodePath.default.join(fixtureSubdir, p)); | ||
}); | ||
const { | ||
plugin, | ||
basePluginOptions, | ||
preset, | ||
basePresetOptions, | ||
baseBabelOptions, | ||
endOfLine, | ||
baseFormatResult, | ||
baseFixtureOutputExt, | ||
baseFixtureOutputName | ||
} = baseConfig; | ||
const { | ||
babelOptions, | ||
pluginOptions, | ||
presetOptions, | ||
title, | ||
only, | ||
skip, | ||
throws, | ||
error, | ||
setup, | ||
teardown, | ||
formatResult, | ||
fixtureOutputName, | ||
fixtureOutputExt | ||
} = localOptions; | ||
const code = readCode(codePath); | ||
const exec = readCode(execPath); | ||
const outputExtension = (fixtureOutputExt || baseFixtureOutputExt || (codeFilename || execFilename).split('.').pop()).replace(/^\./, ''); | ||
const fixtureOutputBasename = `${fixtureOutputName || baseFixtureOutputName}.${outputExtension}`; | ||
const outputPath = _nodePath.default.join(fixtureSubdir, fixtureOutputBasename); | ||
const hasOutputFile = outputPath && _nodeFs.default.existsSync(outputPath); | ||
const output = hasOutputFile ? trimAndFixLineEndings(readCode(outputPath), endOfLine, code) : undefined; | ||
const testConfig = (0, _lodash.default)({ | ||
[_symbols.$type]: 'fixture-object' | ||
}, { | ||
babelOptions: baseBabelOptions | ||
}, { | ||
babelOptions: { | ||
filename: codePath || execPath, | ||
babelrc: hasBabelrc | ||
} | ||
}, { | ||
babelOptions: babelOptions || {} | ||
}, { | ||
babelOptions: { | ||
plugins: [], | ||
presets: [] | ||
}, | ||
testBlockTitle: (() => { | ||
const titleString = title || blockTitle; | ||
if (useFixtureTitleNumbering) { | ||
const numericPrefix = currentTestNumber++; | ||
return { | ||
numericPrefix, | ||
titleString, | ||
fullString: `${numericPrefix}. ${titleString}` | ||
}; | ||
} else { | ||
return { | ||
numericPrefix: undefined, | ||
titleString, | ||
fullString: titleString | ||
}; | ||
} | ||
})(), | ||
only, | ||
skip, | ||
expectedError: throws ?? error, | ||
testSetup: setup || noop, | ||
testTeardown: teardown || noop, | ||
formatResult: formatResult || baseFormatResult, | ||
fixtureOutputBasename, | ||
code, | ||
codeFixture: codePath, | ||
output, | ||
outputFixture: outputPath, | ||
exec, | ||
execFixture: execPath | ||
}, mergeCustomizer); | ||
verbose3('partially constructed fixture-based test object: %O', testConfig); | ||
if (plugin) { | ||
testConfig.babelOptions.plugins.push([plugin, (0, _lodash.default)({}, basePluginOptions, pluginOptions, mergeCustomizer)]); | ||
} else { | ||
testConfig.babelOptions.presets.unshift([preset, (0, _lodash.default)({}, basePresetOptions, presetOptions, mergeCustomizer)]); | ||
} | ||
finalizePluginAndPresetRunOrder(testConfig.babelOptions); | ||
verbose3('finalized fixture-based test object: %O', testConfig); | ||
validateTestConfig(testConfig); | ||
hasTests = true; | ||
((parentDescribeConfig === null || parentDescribeConfig === void 0 ? void 0 : parentDescribeConfig.tests) || testConfigs).push(testConfig); | ||
} | ||
}); | ||
} | ||
function createTestConfig(testObject) { | ||
const { | ||
verbose: verbose3 | ||
} = getDebuggers('create-obj', debug2); | ||
verbose3('generating new test object'); | ||
if (typeof testObject === 'string') { | ||
testObject = { | ||
code: testObject | ||
}; | ||
} | ||
verbose3('raw test object: %O', testObject); | ||
const { | ||
plugin, | ||
pluginName, | ||
basePluginOptions, | ||
preset, | ||
presetName, | ||
basePresetOptions, | ||
baseBabelOptions, | ||
endOfLine, | ||
baseFormatResult, | ||
baseSnapshot | ||
} = baseConfig; | ||
const { | ||
babelOptions, | ||
pluginOptions, | ||
presetOptions, | ||
title, | ||
only, | ||
skip, | ||
only, | ||
title, | ||
code, | ||
babelOptions, | ||
output, | ||
snapshot, | ||
throws, | ||
error, | ||
setup = noop, | ||
setup, | ||
teardown, | ||
formatResult = r => r, | ||
formatResult, | ||
snapshot, | ||
code: rawCode, | ||
output: rawOutput, | ||
exec: rawExec, | ||
fixture, | ||
testFilepath: testFilename = fixture || filename | ||
} = (0, _lodash.default)({}, testerConfig, toTestConfig(testConfig), mergeCustomizer); | ||
(0, _assert.default)(!skip && !only || skip !== only, 'Cannot enable both skip and only on a test'); | ||
if (skip) { | ||
// eslint-disable-next-line jest/no-disabled-tests | ||
it.skip(title, testerWrapper); | ||
} else if (only) { | ||
// eslint-disable-next-line jest/no-focused-tests | ||
it.only(title, testerWrapper); | ||
codeFixture: rawCodeFixture, | ||
outputFixture, | ||
execFixture: rawExecFixture | ||
} = (0, _lodash.default)({ | ||
setup: noop, | ||
teardown: noop | ||
}, testObject, mergeCustomizer); | ||
const codeFixture = getAbsolutePathUsingFilepathDirname(filepath, rawCodeFixture ?? fixture); | ||
const execFixture = getAbsolutePathUsingFilepathDirname(filepath, rawExecFixture); | ||
const code = rawCode !== undefined ? (0, _stripIndent.default)(rawCode) : readCode(codeFixture); | ||
const output = rawOutput !== undefined ? (0, _stripIndent.default)(rawOutput) : readCode(filepath, outputFixture); | ||
const exec = rawExec ?? readCode(execFixture); | ||
const testConfig = (0, _lodash.default)({ | ||
[_symbols.$type]: 'test-object' | ||
}, { | ||
babelOptions: baseBabelOptions | ||
}, { | ||
babelOptions: { | ||
filename: codeFixture || execFixture || filepath || baseBabelOptions.filename | ||
} | ||
}, { | ||
babelOptions: babelOptions || {} | ||
}, { | ||
babelOptions: { | ||
plugins: [], | ||
presets: [] | ||
}, | ||
snapshot: snapshot ?? baseSnapshot, | ||
testBlockTitle: (() => { | ||
const titleString = title || pluginName || presetName; | ||
if (useTestObjectTitleNumbering) { | ||
const numericPrefix = currentTestNumber++; | ||
return { | ||
numericPrefix, | ||
titleString, | ||
fullString: `${numericPrefix}. ${titleString}` | ||
}; | ||
} else { | ||
return { | ||
numericPrefix: undefined, | ||
titleString, | ||
fullString: titleString | ||
}; | ||
} | ||
})(), | ||
only, | ||
skip, | ||
expectedError: throws ?? error, | ||
testSetup: setup || noop, | ||
testTeardown: teardown || noop, | ||
formatResult: formatResult || baseFormatResult, | ||
code, | ||
codeFixture, | ||
output: output !== undefined ? trimAndFixLineEndings(output, endOfLine, code) : undefined, | ||
outputFixture, | ||
exec, | ||
execFixture | ||
}, mergeCustomizer); | ||
verbose3('partially constructed test object: %O', testConfig); | ||
if (plugin) { | ||
testConfig.babelOptions.plugins.push([plugin, (0, _lodash.default)({}, basePluginOptions, pluginOptions, mergeCustomizer)]); | ||
} else { | ||
it(title, testerWrapper); | ||
testConfig.babelOptions.presets.unshift([preset, (0, _lodash.default)({}, basePresetOptions, presetOptions, mergeCustomizer)]); | ||
} | ||
function testerWrapper() { | ||
return _testerWrapper.apply(this, arguments); | ||
} // eslint-disable-next-line complexity | ||
function _testerWrapper() { | ||
_testerWrapper = _asyncToGenerator(function* () { | ||
const teardowns = teardown ? [teardown] : []; | ||
let returnedTeardown; | ||
try { | ||
returnedTeardown = yield setup(); | ||
} catch (e) { | ||
// eslint-disable-next-line no-console | ||
console.error('There was a problem during setup'); | ||
throw e; | ||
finalizePluginAndPresetRunOrder(testConfig.babelOptions); | ||
verbose3('finalized test object: %O', testConfig); | ||
validateTestConfig(testConfig, { | ||
hasCodeAndCodeFixture: !!(rawCode && codeFixture), | ||
hasOutputAndOutputFixture: !!(rawOutput && outputFixture), | ||
hasExecAndExecFixture: !!(rawExec && execFixture) | ||
}); | ||
hasTests = true; | ||
return testConfig; | ||
} | ||
} | ||
function registerTestsWithTestingFramework(tests) { | ||
const { | ||
debug: debug2 | ||
} = getDebuggers('register', debug1); | ||
debug2(`registering ${tests.length} blocks with testing framework`); | ||
tests.forEach(testConfig => { | ||
if (testConfig[_symbols.$type] == 'describe-block') { | ||
debug2(`registering describe block "${testConfig.describeBlockTitle}" and its sub-blocks`); | ||
describe(testConfig.describeBlockTitle, () => { | ||
registerTestsWithTestingFramework(testConfig.tests); | ||
}); | ||
} else { | ||
var _envConfig$skipTestsB, _envConfig$onlyTestsB; | ||
const { | ||
skip, | ||
only, | ||
testBlockTitle: { | ||
numericPrefix, | ||
titleString, | ||
fullString | ||
} | ||
if (typeof returnedTeardown === 'function') { | ||
teardowns.push(returnedTeardown); | ||
} = testConfig; | ||
let method = undefined; | ||
if ((_envConfig$skipTestsB = envConfig.skipTestsByRegExp) !== null && _envConfig$skipTestsB !== void 0 && _envConfig$skipTestsB.test(titleString) || numericPrefixInRanges(numericPrefix, envConfig.skipTestsByRange)) { | ||
method = 'skip'; | ||
debug2(`registering test block "${fullString}" (with \`skip\` property enabled via environment variable)`); | ||
} else if ((_envConfig$onlyTestsB = envConfig.onlyTestsByRegExp) !== null && _envConfig$onlyTestsB !== void 0 && _envConfig$onlyTestsB.test(titleString) || numericPrefixInRanges(numericPrefix, envConfig.onlyTestsByRange)) { | ||
method = 'only'; | ||
debug2(`registering test block "${fullString}" (with \`only\` property enabled via environment variable)`); | ||
} else if (skip) { | ||
method = 'skip'; | ||
debug2(`registering test block "${fullString}" (with \`skip\` property enabled)`); | ||
} else if (only) { | ||
method = 'only'; | ||
debug2(`registering test block "${fullString}" (with \`only\` property enabled)`); | ||
} else { | ||
debug2(`registering test block "${fullString}"`); | ||
} | ||
(method ? it[method] : it)(fullString, frameworkTestWrapper(testConfig)); | ||
} | ||
}); | ||
} | ||
function frameworkTestWrapper(testConfig) { | ||
const { | ||
verbose: verbose2 | ||
} = getDebuggers('wrapper', debug1); | ||
return async () => { | ||
const { | ||
baseSetup, | ||
baseTeardown | ||
} = baseConfig; | ||
const { | ||
testSetup, | ||
testTeardown | ||
} = testConfig; | ||
const setupFunctions = [baseSetup, testSetup]; | ||
const teardownFunctions = [testTeardown, baseTeardown]; | ||
for (const [index, setupFn] of setupFunctions.entries()) { | ||
verbose2(`running setup function #${index + 1}${setupFn === noop ? ' (noop)' : ''}`); | ||
try { | ||
const maybeTeardownFn = await setupFn(); | ||
if (typeof maybeTeardownFn === 'function') { | ||
verbose2(`registered teardown function returned from setup function #${index + 1}`); | ||
teardownFunctions.splice(index - 1, 0, maybeTeardownFn); | ||
} | ||
} catch (error) { | ||
const message = _errors.ErrorMessage.SetupFunctionFailed(error); | ||
verbose2(message); | ||
throw new Error(message, { | ||
cause: error | ||
}); | ||
} | ||
} | ||
let frameworkError; | ||
try { | ||
await frameworkTest(testConfig); | ||
} catch (error) { | ||
frameworkError = error; | ||
verbose2('caught framework test failure'); | ||
} finally { | ||
for (const [index, teardownFn] of teardownFunctions.entries()) { | ||
verbose2(`running teardown function #${index + 1}${teardownFn === noop ? ' (noop)' : ''}`); | ||
try { | ||
yield tester(); | ||
} finally { | ||
try { | ||
yield Promise.all(teardowns.map(t => t())); | ||
} catch (e) { | ||
// eslint-disable-next-line no-console | ||
console.error('There was a problem during teardown'); // eslint-disable-next-line no-unsafe-finally | ||
throw e; | ||
} | ||
await teardownFn(); | ||
} catch (error) { | ||
const message = _errors.ErrorMessage.TeardownFunctionFailed(error, frameworkError); | ||
verbose2(message); | ||
throw new Error(message, { | ||
cause: { | ||
error, | ||
frameworkError | ||
} | ||
}); | ||
} | ||
}); | ||
return _testerWrapper.apply(this, arguments); | ||
} | ||
if (frameworkError) { | ||
verbose2('rethrowing framework test failure'); | ||
throw frameworkError; | ||
} | ||
} | ||
function tester() { | ||
return _tester.apply(this, arguments); | ||
}; | ||
} | ||
async function frameworkTest(testConfig) { | ||
const { | ||
debug: debug2, | ||
verbose: verbose2 | ||
} = getDebuggers('test', debug1); | ||
const { | ||
babel, | ||
endOfLine, | ||
filepath | ||
} = baseConfig; | ||
const { | ||
babelOptions, | ||
testBlockTitle, | ||
expectedError, | ||
formatResult, | ||
code, | ||
codeFixture, | ||
output, | ||
outputFixture, | ||
exec, | ||
execFixture | ||
} = testConfig; | ||
debug2(`test framework has triggered test "${testBlockTitle.fullString}"`); | ||
let errored = false; | ||
const rawBabelOutput = await (async () => { | ||
try { | ||
var _await$transformer; | ||
const transformer = babel.transformAsync || babel.transform; | ||
const parameters = [code ?? exec, babelOptions]; | ||
verbose2(`calling babel transform function (${transformer.name}) with parameters: %O`, parameters); | ||
return (_await$transformer = await transformer(...parameters)) === null || _await$transformer === void 0 ? void 0 : _await$transformer.code; | ||
} catch (error) { | ||
verbose2(`babel transformation failed with error: ${error}`); | ||
if (expectedError) { | ||
errored = true; | ||
return error; | ||
} else { | ||
throw error; | ||
} | ||
} | ||
function _tester() { | ||
_tester = _asyncToGenerator(function* () { | ||
(0, _assert.default)(code, 'A string or object with a `code` or `fixture` property must be provided'); | ||
(0, _assert.default)(!babelOptions.babelrc || babelOptions.filename, 'babelrc set to true, but no filename specified in babelOptions'); | ||
(0, _assert.default)(!snapshot || !output, '`output` cannot be provided with `snapshot: true`'); | ||
let result, transformed; | ||
let errored = false; | ||
try { | ||
if (babel.transformAsync) { | ||
transformed = yield babel.transformAsync(code, babelOptions); | ||
} else { | ||
transformed = babel.transform(code, babelOptions); | ||
} | ||
result = formatResult(fixLineEndings(transformed.code, endOfLine, code), { | ||
filename: testFilename | ||
}); | ||
} catch (err) { | ||
if (error) { | ||
errored = true; | ||
result = err; | ||
} else { | ||
throw err; | ||
} | ||
})(); | ||
try { | ||
if (expectedError) { | ||
debug2('expecting babel transform function to fail with error'); | ||
(0, _nodeAssert.default)(errored, _errors.ErrorMessage.ExpectedBabelToThrow()); | ||
if (typeof expectedError === 'function') { | ||
if (expectedError === Error || expectedError.prototype instanceof Error) { | ||
(0, _nodeAssert.default)(rawBabelOutput instanceof expectedError, _errors.ErrorMessage.ExpectedErrorToBeInstanceOf(expectedError)); | ||
} else if (expectedError(rawBabelOutput) !== true) { | ||
_nodeAssert.default.fail(_errors.ErrorMessage.ExpectedThrowsFunctionToReturnTrue()); | ||
} | ||
const expectedToThrowButDidNot = error && !errored; | ||
(0, _assert.default)(!expectedToThrowButDidNot, 'Expected to throw error, but it did not.'); | ||
if (snapshot) { | ||
(0, _assert.default)(result !== code, 'Code was unmodified but attempted to take a snapshot. If the code should not be modified, set `snapshot: false`'); | ||
const separator = '\n\n ↓ ↓ ↓ ↓ ↓ ↓\n\n'; | ||
const formattedOutput = [code, separator, result].join(''); | ||
expect(`\n${formattedOutput}\n`).toMatchSnapshot(title); | ||
} else if (error) { | ||
assertError(result, error); | ||
} else if (typeof output === 'string') { | ||
_assert.default.equal(result.trim(), output.trim(), 'Output is incorrect.'); | ||
} else { | ||
_assert.default.equal(result.trim(), fixLineEndings(code, endOfLine), 'Expected output to not change, but it did'); | ||
} else { | ||
const resultString = (0, _types.isNativeError)(rawBabelOutput) ? rawBabelOutput.message : String(rawBabelOutput); | ||
if (typeof expectedError === 'string') { | ||
(0, _nodeAssert.default)(resultString.includes(expectedError), _errors.ErrorMessage.ExpectedErrorToIncludeString(resultString, expectedError)); | ||
} else if (expectedError instanceof RegExp) { | ||
(0, _nodeAssert.default)(expectedError.test(resultString), _errors.ErrorMessage.ExpectedErrorToMatchRegExp(resultString, expectedError)); | ||
} | ||
}); | ||
return _tester.apply(this, arguments); | ||
} | ||
} else if (typeof rawBabelOutput !== 'string') { | ||
throw new TypeError(_errors.ErrorMessage.BabelOutputTypeIsNotString(rawBabelOutput)); | ||
} else { | ||
debug2('expecting babel transform function to succeed'); | ||
const formatResultFilepath = codeFixture || execFixture || filepath; | ||
const result = trimAndFixLineEndings(formatResult(rawBabelOutput || '', { | ||
cwd: formatResultFilepath ? _nodePath.default.dirname(formatResultFilepath) : undefined, | ||
filepath: formatResultFilepath, | ||
filename: formatResultFilepath | ||
}), endOfLine, code); | ||
if (exec !== undefined) { | ||
debug2('executing output from babel transform function'); | ||
(0, _nodeAssert.default)(result.length > 0, _errors.ErrorMessage.BabelOutputUnexpectedlyEmpty()); | ||
const fakeModule = { | ||
exports: {} | ||
}; | ||
const context = (0, _nodeVm.createContext)({ | ||
...globalThis, | ||
module: fakeModule, | ||
exports: fakeModule.exports, | ||
require | ||
}); | ||
new _nodeVm.Script(result, { | ||
filename: execFixture | ||
}).runInContext(context, { | ||
displayErrors: true, | ||
breakOnSigint: true, | ||
microtaskMode: 'afterEvaluate' | ||
}); | ||
} else if (testConfig[_symbols.$type] == 'test-object' && testConfig.snapshot) { | ||
debug2('expecting output from babel transform function to match snapshot'); | ||
(0, _nodeAssert.default)(result !== code, _errors.ErrorMessage.AttemptedToSnapshotUnmodifiedBabelOutput()); | ||
const separator = '\n\n ↓ ↓ ↓ ↓ ↓ ↓\n\n'; | ||
const formattedOutput = [code, separator, result].join(''); | ||
expect(`\n${formattedOutput}\n`).toMatchSnapshot(testBlockTitle.fullString); | ||
} else if (output !== undefined) { | ||
debug2('expecting output from babel transform function to match expected output'); | ||
_nodeAssert.default.equal(result, output, _errors.ErrorMessage.ExpectedOutputToEqualActual(testConfig)); | ||
} else if (testConfig[_symbols.$type] == 'fixture-object' && outputFixture) { | ||
debug2('writing output from babel transform function to new output file'); | ||
_nodeFs.default.writeFileSync(outputFixture, result); | ||
} else { | ||
debug2('expecting output from babel transform function to match input'); | ||
_nodeAssert.default.equal(result, trimAndFixLineEndings(code, endOfLine), _errors.ErrorMessage.ExpectedOutputNotToChange()); | ||
} | ||
} | ||
}); | ||
}); | ||
function toTestConfig(testConfig) { | ||
if (typeof testConfig === 'string') { | ||
testConfig = { | ||
code: testConfig | ||
}; | ||
} catch (error) { | ||
verbose2(`test failed: ${error}`); | ||
throw error; | ||
} | ||
} | ||
function validateTestConfig(testConfig, knownViolations) { | ||
const { | ||
title, | ||
fixture, | ||
code = getCode(filename, fixture), | ||
fullTitle = title || `${testNumber++}. ${pluginName}`, | ||
output = getCode(filename, testConfig.outputFixture) || undefined, | ||
pluginOptions: testOptions = pluginOptions | ||
verbose: verbose2 | ||
} = getDebuggers('validate', debug1); | ||
verbose2('known violations: %O', knownViolations); | ||
const { | ||
testBlockTitle, | ||
skip, | ||
only, | ||
code, | ||
exec, | ||
output, | ||
babelOptions, | ||
expectedError | ||
} = testConfig; | ||
return (0, _lodash.default)({ | ||
babelOptions: { | ||
filename: getPath(filename, fixture) | ||
if (knownViolations) { | ||
const { | ||
hasCodeAndCodeFixture, | ||
hasOutputAndOutputFixture, | ||
hasExecAndExecFixture | ||
} = knownViolations; | ||
if (hasCodeAndCodeFixture) { | ||
throwTypeErrorWithDebugOutput(_errors.ErrorMessage.InvalidHasCodeAndCodeFixture()); | ||
} | ||
}, testConfig, _objectSpread({ | ||
babelOptions: { | ||
plugins: [[plugin, testOptions]] | ||
}, | ||
title: fullTitle, | ||
code: (0, _stripIndent.default)(code).trim() | ||
}, output ? { | ||
output: (0, _stripIndent.default)(output).trim() | ||
} : {}), mergeCustomizer); | ||
if (hasOutputAndOutputFixture) { | ||
throwTypeErrorWithDebugOutput(_errors.ErrorMessage.InvalidHasOutputAndOutputFixture()); | ||
} | ||
if (hasExecAndExecFixture) { | ||
throwTypeErrorWithDebugOutput(_errors.ErrorMessage.InvalidHasExecAndExecFixture()); | ||
} | ||
} | ||
if (testConfig[_symbols.$type] == 'test-object' && testConfig.snapshot) { | ||
if (!globalContextExpectFnHasToMatchSnapshot) { | ||
throwTypeErrorWithDebugOutput(_errors.ErrorMessage.TestEnvironmentNoSnapshotSupport()); | ||
} | ||
if (output !== undefined) { | ||
throwTypeErrorWithDebugOutput(_errors.ErrorMessage.InvalidHasSnapshotAndOutput()); | ||
} | ||
if (exec !== undefined) { | ||
throwTypeErrorWithDebugOutput(_errors.ErrorMessage.InvalidHasSnapshotAndExec()); | ||
} | ||
if (expectedError !== undefined) { | ||
throwTypeErrorWithDebugOutput(_errors.ErrorMessage.InvalidHasSnapshotAndThrows()); | ||
} | ||
} | ||
if (skip && only) { | ||
throwTypeErrorWithDebugOutput(_errors.ErrorMessage.InvalidHasSkipAndOnly()); | ||
} | ||
if (skip && !globalContextTestFnHasSkip) { | ||
throwTypeErrorWithDebugOutput(_errors.ErrorMessage.TestEnvironmentNoSkipSupport()); | ||
} | ||
if (only && !globalContextTestFnHasOnly) { | ||
throwTypeErrorWithDebugOutput(_errors.ErrorMessage.TestEnvironmentNoOnlySupport()); | ||
} | ||
if (output !== undefined && expectedError !== undefined) { | ||
throwTypeErrorWithDebugOutput(_errors.ErrorMessage.InvalidHasThrowsAndOutput(testConfig)); | ||
} | ||
if (exec !== undefined && expectedError !== undefined) { | ||
throwTypeErrorWithDebugOutput(_errors.ErrorMessage.InvalidHasThrowsAndExec(testConfig)); | ||
} | ||
if (code === undefined && exec === undefined) { | ||
throwTypeErrorWithDebugOutput(_errors.ErrorMessage.InvalidMissingCodeOrExec(testConfig)); | ||
} | ||
if ((code !== undefined || output !== undefined) && exec !== undefined) { | ||
throwTypeErrorWithDebugOutput(_errors.ErrorMessage.InvalidHasExecAndCodeOrOutput(testConfig)); | ||
} | ||
if (babelOptions.babelrc && !babelOptions.filename) { | ||
throwTypeErrorWithDebugOutput(_errors.ErrorMessage.InvalidHasBabelrcButNoFilename()); | ||
} | ||
if (expectedError !== undefined && !(['function', 'boolean', 'string'].includes(typeof expectedError) || expectedError instanceof RegExp)) { | ||
throwTypeErrorWithDebugOutput(_errors.ErrorMessage.InvalidThrowsType()); | ||
} | ||
function throwTypeErrorWithDebugOutput(message) { | ||
const finalMessage = _errors.ErrorMessage.ValidationFailed(testBlockTitle.fullString, message); | ||
verbose2(finalMessage); | ||
throw new TypeError(finalMessage); | ||
} | ||
} | ||
} | ||
function fixLineEndings(string, endOfLine, input = string) { | ||
return String(string).replace(/\r?\n/g, getReplacement()).trim(); | ||
function mergeCustomizer(objValue, srcValue, key, object, source) { | ||
if (object && srcValue === undefined && key in source) { | ||
delete object[key]; | ||
} else if (Array.isArray(objValue)) { | ||
return objValue.concat(srcValue); | ||
} | ||
return undefined; | ||
} | ||
function getAbsolutePathUsingFilepathDirname(filepath, basename) { | ||
const { | ||
verbose: verbose2 | ||
} = getDebuggers('to-abs-path', debug1); | ||
const result = !basename ? undefined : _nodePath.default.isAbsolute(basename) ? basename : filepath ? _nodePath.default.join(_nodePath.default.dirname(filepath), basename) : undefined; | ||
verbose2(`dirname(${filepath}) + ${basename} => ${result}`); | ||
return result; | ||
} | ||
function readFixtureOptions(baseDirectory) { | ||
const { | ||
verbose: verbose2 | ||
} = getDebuggers('read-opts', debug1); | ||
const optionsPath = [_nodePath.default.join(baseDirectory, 'options.js'), _nodePath.default.join(baseDirectory, 'options.json')].find(p => _nodeFs.default.existsSync(p)); | ||
try { | ||
if (optionsPath) { | ||
verbose2(`requiring options file ${optionsPath}`); | ||
return require(optionsPath); | ||
} else { | ||
verbose2('attempt to require options file ignored: no such file exists'); | ||
return {}; | ||
} | ||
} catch (error) { | ||
const message = _errors.ErrorMessage.GenericErrorWithPath(error, optionsPath); | ||
verbose2(`attempt to require options file failed: ${message}`); | ||
throw new Error(message); | ||
} | ||
} | ||
function readCode(filepath, basename) { | ||
const { | ||
verbose: verbose2 | ||
} = getDebuggers('read-code', debug1); | ||
const codePath = arguments.length == 1 ? filepath : getAbsolutePathUsingFilepathDirname(filepath, basename); | ||
if (!codePath) { | ||
verbose2(`attempt to read in contents from file ignored: no absolute path derivable from filepath "${filepath}" and basename "${basename}"`); | ||
return undefined; | ||
} | ||
if (!_nodePath.default.isAbsolute(codePath)) { | ||
const message = _errors.ErrorMessage.PathIsNotAbsolute(codePath); | ||
verbose2(`attempt to read in contents from file failed: ${message}`); | ||
throw new Error(message); | ||
} | ||
try { | ||
verbose2(`reading in contents from file ${codePath}`); | ||
return _nodeFs.default.readFileSync(codePath, 'utf8'); | ||
} catch (error) { | ||
const message = _errors.ErrorMessage.GenericErrorWithPath(error, codePath); | ||
verbose2(`attempt to read in contents from file failed: ${message}`); | ||
throw new Error(message); | ||
} | ||
} | ||
function trimAndFixLineEndings(source, endOfLine, input = source) { | ||
const { | ||
verbose: verbose2 | ||
} = getDebuggers('eol', debug1); | ||
source = source.trim(); | ||
if (endOfLine === false) { | ||
verbose2('no EOL fix applied: EOL conversion disabled'); | ||
return source; | ||
} | ||
verbose2(`applying EOL fix "${endOfLine}": all EOL will be replaced`); | ||
verbose2('input (trimmed) with original EOL: %O', source.replaceAll('\r', '\\r').replaceAll('\n', '\\n')); | ||
const output = source.replaceAll(/\r?\n/g, getReplacement()).trim(); | ||
verbose2('output (trimmed) with EOL fix applied: %O', output.replaceAll('\r', '\\r').replaceAll('\n', '\\n')); | ||
return output; | ||
function getReplacement() { | ||
@@ -272,3 +1045,2 @@ switch (endOfLine) { | ||
} | ||
case 'crlf': | ||
@@ -278,22 +1050,18 @@ { | ||
} | ||
case 'auto': | ||
{ | ||
return _os.EOL; | ||
return _nodeOs.EOL; | ||
} | ||
case 'preserve': | ||
{ | ||
const match = input.match(/\r?\n/); | ||
if (match === null) { | ||
return _os.EOL; | ||
return _nodeOs.EOL; | ||
} | ||
return match[0]; | ||
} | ||
default: | ||
{ | ||
throw new Error("Invalid 'endOfLine' value"); | ||
verbose2(`encountered invalid EOL option "${endOfLine}"`); | ||
throw new TypeError(_errors.ErrorMessage.BadConfigInvalidEndOfLine(endOfLine)); | ||
} | ||
@@ -303,198 +1071,51 @@ } | ||
} | ||
const createFixtureTests = (fixturesDir, options) => { | ||
if (!_fs.default.statSync(fixturesDir).isDirectory()) return; | ||
const rootOptionsPath = _path.default.join(fixturesDir, 'options.json'); | ||
let rootFixtureOptions = {}; | ||
if (_fs.default.existsSync(rootOptionsPath)) { | ||
rootFixtureOptions = require(rootOptionsPath); | ||
function finalizePluginAndPresetRunOrder(babelOptions) { | ||
const { | ||
verbose: verbose2 | ||
} = getDebuggers('finalize', debug1); | ||
if (babelOptions !== null && babelOptions !== void 0 && babelOptions.plugins) { | ||
babelOptions.plugins = babelOptions.plugins.filter(p => { | ||
const result = Boolean(p); | ||
if (!result) { | ||
verbose2('a falsy `babelOptions.plugins` item was filtered out'); | ||
} | ||
return result; | ||
}); | ||
if (babelOptions.plugins.includes(runPluginUnderTestHere)) { | ||
verbose2('replacing `runPluginUnderTestHere` symbol in `babelOptions.plugins` with plugin under test'); | ||
babelOptions.plugins.splice(babelOptions.plugins.indexOf(runPluginUnderTestHere), 1, babelOptions.plugins.pop()); | ||
} | ||
} | ||
_fs.default.readdirSync(fixturesDir).forEach(caseName => { | ||
const fixtureDir = _path.default.join(fixturesDir, caseName); | ||
const optionsPath = _path.default.join(fixtureDir, 'options.json'); | ||
const jsCodePath = _path.default.join(fixtureDir, 'code.js'); | ||
const tsCodePath = _path.default.join(fixtureDir, 'code.ts'); | ||
const jsxCodePath = _path.default.join(fixtureDir, 'code.jsx'); | ||
const tsxCodePath = _path.default.join(fixtureDir, 'code.tsx'); | ||
const blockTitle = caseName.split('-').join(' '); | ||
const codePath = _fs.default.existsSync(jsCodePath) && jsCodePath || _fs.default.existsSync(tsCodePath) && tsCodePath || _fs.default.existsSync(jsxCodePath) && jsxCodePath || _fs.default.existsSync(tsxCodePath) && tsxCodePath; | ||
let fixturePluginOptions = {}; | ||
if (_fs.default.existsSync(optionsPath)) { | ||
fixturePluginOptions = require(optionsPath); | ||
} | ||
if (!codePath) { | ||
describe(blockTitle, () => { | ||
createFixtureTests(fixtureDir, _objectSpread(_objectSpread({}, options), {}, { | ||
pluginOptions: _objectSpread(_objectSpread(_objectSpread({}, rootFixtureOptions), options.pluginOptions), fixturePluginOptions) | ||
})); | ||
}); | ||
return; | ||
} | ||
it(blockTitle, /*#__PURE__*/_asyncToGenerator(function* () { | ||
const { | ||
plugin, | ||
pluginOptions, | ||
fixtureOutputName, | ||
babel, | ||
endOfLine, | ||
formatResult = r => r | ||
} = options, | ||
rest = _objectWithoutProperties(options, _excluded2); | ||
const hasBabelrc = ['.babelrc', '.babelrc.js', '.babelrc.cjs'].some(babelrc => _fs.default.existsSync(_path.default.join(fixtureDir, babelrc))); | ||
const { | ||
babelOptions | ||
} = (0, _lodash.default)({}, fullDefaultConfig, { | ||
babelOptions: { | ||
plugins: [[plugin, _objectSpread(_objectSpread(_objectSpread({}, rootFixtureOptions), pluginOptions), fixturePluginOptions)]], | ||
// if they have a babelrc, then we'll let them use that | ||
// otherwise, we'll just use our simple config | ||
babelrc: hasBabelrc | ||
} | ||
}, rest, mergeCustomizer); | ||
const input = _fs.default.readFileSync(codePath).toString(); | ||
let transformed, ext; | ||
if (babel.transformAsync) { | ||
transformed = yield babel.transformAsync(input, _objectSpread(_objectSpread({}, babelOptions), {}, { | ||
filename: codePath | ||
})); | ||
} else { | ||
transformed = babel.transform(input, _objectSpread(_objectSpread({}, babelOptions), {}, { | ||
filename: codePath | ||
})); | ||
if (babelOptions !== null && babelOptions !== void 0 && babelOptions.presets) { | ||
babelOptions.presets = babelOptions.presets.filter(p => { | ||
const result = Boolean(p); | ||
if (!result) { | ||
verbose2('a falsy `babelOptions.presets` item was filtered out'); | ||
} | ||
const actual = formatResult(fixLineEndings(transformed.code, endOfLine, input)); | ||
const { | ||
fixtureOutputExt | ||
} = fixturePluginOptions; | ||
if (fixtureOutputExt) { | ||
ext = fixtureOutputExt; | ||
} else { | ||
ext = `.${codePath.split('.').pop()}`; | ||
} | ||
const outputPath = _path.default.join(fixtureDir, `${fixtureOutputName}${ext}`); | ||
if (!_fs.default.existsSync(outputPath)) { | ||
_fs.default.writeFileSync(outputPath, actual); | ||
return; | ||
} | ||
const output = _fs.default.readFileSync(outputPath, 'utf8'); | ||
_assert.default.equal(actual.trim(), fixLineEndings(output, endOfLine), `actual output does not match ${fixtureOutputName}${ext}`); | ||
})); | ||
}); | ||
}; | ||
function testFixtures(_ref3) { | ||
let { | ||
title: describeBlockTitle, | ||
fixtures, | ||
filename | ||
} = _ref3, | ||
rest = _objectWithoutProperties(_ref3, _excluded3); | ||
describe(`${describeBlockTitle} fixtures`, () => { | ||
const fixturesDir = getPath(filename, fixtures); | ||
createFixtureTests(fixturesDir, rest); | ||
}); | ||
} | ||
function toTestArray(tests) { | ||
tests = tests || []; // null/0/false are ok, so no default param | ||
if (Array.isArray(tests)) { | ||
return tests; | ||
} | ||
return Object.keys(tests).reduce((testsArray, key) => { | ||
let value = tests[key]; | ||
if (typeof value === 'string') { | ||
value = { | ||
code: value | ||
}; | ||
return result; | ||
}); | ||
if (babelOptions.presets.includes(runPresetUnderTestHere)) { | ||
verbose2('replacing `runPresetUnderTestHere` symbol in `babelOptions.presets` with preset under test'); | ||
babelOptions.presets.splice(babelOptions.presets.indexOf(runPresetUnderTestHere) - 1, 1, babelOptions.presets.shift()); | ||
} | ||
testsArray.push(_objectSpread({ | ||
title: key | ||
}, value)); | ||
return testsArray; | ||
}, []); | ||
} | ||
function getCode(filename, fixture) { | ||
if (!fixture) { | ||
return ''; | ||
} | ||
return _fs.default.readFileSync(getPath(filename, fixture), 'utf8'); | ||
verbose2('finalized test object plugin and preset run order'); | ||
} | ||
function getPath(filename, basename) { | ||
if (!basename) { | ||
return undefined; | ||
function numericPrefixInRanges(numericPrefix, ranges) { | ||
if (typeof numericPrefix == 'number') { | ||
return ranges.some(range => { | ||
return typeof range == 'number' ? numericPrefix == range : numericPrefix >= range.start && numericPrefix <= range.end; | ||
}); | ||
} | ||
if (_path.default.isAbsolute(basename)) { | ||
return basename; | ||
} | ||
return _path.default.join(_path.default.dirname(filename), basename); | ||
} // eslint-disable-next-line complexity | ||
function assertError(result, error) { | ||
if (typeof error === 'function') { | ||
if (!(instanceOf(result, error) || error(result) === true)) { | ||
throw result; | ||
} | ||
} else if (typeof error === 'string') { | ||
(0, _assert.default)(result.message.includes(error), 'Error message is incorrect'); | ||
} else if (error instanceof RegExp) { | ||
(0, _assert.default)(error.test(result.message), `Expected ${result.message} to match ${error}`); | ||
} else { | ||
(0, _assert.default)(typeof error === 'boolean', 'The given `error` must be a function, string, boolean, or RegExp'); | ||
} | ||
return false; | ||
} | ||
function requiredParam(name) { | ||
throw new Error(`${name} is a required parameter.`); | ||
} | ||
var _default = pluginTester; // unfortunately the ESLint plugin for Jest thinks this is a test file | ||
// a better solution might be to adjust the eslint config so it doesn't | ||
// but I don't have time to do that at the moment. | ||
/* | ||
eslint | ||
complexity: off, | ||
jest/valid-describe: off, | ||
jest/no-if: off, | ||
jest/valid-title: off, | ||
jest/no-export: off, | ||
jest/no-try-expect: off, | ||
jest/no-conditional-expect: off, | ||
*/ | ||
exports.default = _default; | ||
pluginTester.default = pluginTester; | ||
pluginTester.pluginTester = pluginTester; | ||
pluginTester.restartTestTitleNumbering = restartTestTitleNumbering; | ||
pluginTester.prettierFormatter = _prettier.prettierFormatter; | ||
pluginTester.unstringSnapshotSerializer = _unstringSnapshot.unstringSnapshotSerializer; | ||
pluginTester.runPluginUnderTestHere = runPluginUnderTestHere; | ||
pluginTester.runPresetUnderTestHere = runPresetUnderTestHere; | ||
pluginTester.validTitleNumberingValues = validTitleNumberingValues; | ||
pluginTester.validEndOfLineValues = validEndOfLineValues; | ||
module.exports = pluginTester; |
231
package.json
{ | ||
"name": "babel-plugin-tester", | ||
"version": "10.1.0", | ||
"version": "11.0.0-canary.1", | ||
"description": "Utilities for testing babel plugins", | ||
"main": "dist/index.js", | ||
"engines": { | ||
"node": ">=10.13", | ||
"npm": ">=6" | ||
"keywords": [ | ||
"babel", | ||
"plugin", | ||
"tester" | ||
], | ||
"homepage": "https://github.com/babel-utils/babel-plugin-tester#readme", | ||
"bugs": { | ||
"url": "https://github.com/babel-utils/babel-plugin-tester/issues" | ||
}, | ||
"scripts": { | ||
"build": "kcd-scripts build", | ||
"lint": "kcd-scripts lint", | ||
"setup": "npm install && npm run validate -s", | ||
"test": "kcd-scripts test", | ||
"test:update": "npm test -- --updateSnapshot --coverage", | ||
"validate": "kcd-scripts validate" | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/babel-utils/babel-plugin-tester" | ||
}, | ||
"license": "MIT", | ||
"author": "Kent C. Dodds <me@kentcdodds.com> (https://kentcdodds.com)", | ||
"sideEffects": false, | ||
"type": "commonjs", | ||
"exports": { | ||
".": { | ||
"types": "./dist/index.d.ts", | ||
"default": "./dist/index.js" | ||
}, | ||
"./pure": { | ||
"types": "./dist/plugin-tester.d.ts", | ||
"default": "./dist/plugin-tester.js" | ||
}, | ||
"./package": "./package.json", | ||
"./package.json": "./package.json" | ||
}, | ||
"typesVersions": { | ||
"*": { | ||
"pure": [ | ||
"./dist/plugin-tester.d.ts" | ||
], | ||
"*": [ | ||
"./dist/index.d.ts" | ||
] | ||
} | ||
}, | ||
"files": [ | ||
"dist", | ||
"pure.js" | ||
"/dist", | ||
"/LICENSE", | ||
"/package.json", | ||
"/README.md" | ||
], | ||
"keywords": [], | ||
"author": "Kent C. Dodds <me@kentcdodds.com> (https://kentcdodds.com)", | ||
"license": "MIT", | ||
"scripts": { | ||
"build": "npm run build:dist --", | ||
"build:changelog": "conventional-changelog --outfile CHANGELOG.md --config ./conventional.config.js --release-count 0 --skip-unstable && (if [ \"$CHANGELOG_SKIP_TITLE\" != 'true' ]; then { node -e 'console.log(require(\"./conventional.config.js\").changelogTitle)'; cat CHANGELOG.md; } > CHANGELOG.md.ignore && mv CHANGELOG.md.ignore CHANGELOG.md; fi) && NODE_ENV=format remark --output --frail CHANGELOG.md && prettier --write CHANGELOG.md", | ||
"build:dist": "NODE_ENV=production tsc --project tsconfig.types.json --incremental false && tsconfig-replace-paths --project tsconfig.types.json && NODE_ENV=production-cjs babel src --extensions .ts --out-dir dist", | ||
"clean": "git ls-files --exclude-standard --ignored --others --directory | grep -vE '^((\\.(env|vscode|husky))|next-env\\.d\\.ts|node_modules)($|\\/)' | xargs -p rm -rf", | ||
"format": "MD_FILES=$(node -e 'console.log(require(`glob-gitignore`).sync(`**/*.md`, { ignore: require(`fs`).readFileSync(`.prettierignore`, `utf8`).split(`\n`).filter(Boolean), dot: true }).join(`\n`))') && (echo $MD_FILES | xargs remark --no-config --no-stdout --quiet --frail --use gfm --use lint-no-undefined-references || (echo -n '\u001b' && echo '[37;41;1m FAIL \u001b[0m cannot continue with undefined references present' && false)) && sort-package-json './package.json' './packages/*/package.json' && echo $MD_FILES | NODE_ENV=format xargs remark --output --frail && echo $MD_FILES | xargs doctoc --no-title --maxlevel 3 --update-only && prettier --write .", | ||
"lint": "stdbuf -i0 -o0 -e0 tsc --project tsconfig.lint.json; X=$?; stdbuf -i0 -o0 -e0 eslint --parser-options=project:tsconfig.lint.json --no-error-on-unmatched-pattern packages src; Y=$?; MD_FILES=$(node -e 'console.log(require(`glob-gitignore`).sync(`**/*.md`, { ignore: require(`fs`).readFileSync(`.prettierignore`, `utf8`).split(`\n`).filter(Boolean), dot: true }).join(`\n`))') && echo $MD_FILES | NODE_ENV=lint xargs remark --quiet --frail --no-stdout; Z=$?; [ $X -eq 0 ] && [ $Y -eq 0 ] && [ $Z -eq 0 ]", | ||
"lint:all": "stdbuf -i0 -o0 -e0 tsc --project tsconfig.eslint.json; X=$?; stdbuf -i0 -o0 -e0 eslint --parser-options=project:tsconfig.eslint.json .; Y=$?; MD_FILES=$(node -e 'console.log(require(`glob-gitignore`).sync(`**/*.md`, { ignore: require(`fs`).readFileSync(`.prettierignore`, `utf8`).split(`\n`).filter(Boolean), dot: true }).join(`\n`))') && echo $MD_FILES | NODE_ENV=lint xargs remark --quiet --frail --no-stdout; Z=$?; [ $X -eq 0 ] && [ $Y -eq 0 ] && [ $Z -eq 0 ]", | ||
"list-tasks": "node -e 'console.log(Object.keys(require(\"./package.json\").scripts).join(\"\\n\"))' && (npm run -ws list-tasks --if-present 2>/dev/null || true)", | ||
"prepare": "node -e \"execa = require('execa'); if(process.env.CI === undefined && (process.env.NODE_ENV === undefined || process.env.NODE_ENV == 'development')) { execa.sync('npx', ['husky', 'install'], { stdout: 'inherit', stderr: 'inherit' }); } else { console.log('skipped installing husky git hooks'); }\"", | ||
"test": "npm run test:unit --", | ||
"test:all": "NODE_ENV=test jest --coverage", | ||
"test:integration": "NODE_ENV=test jest 'integration-.*\\.test\\.ts.*'", | ||
"test:unit": "NODE_ENV=test jest --testPathIgnorePatterns 'integration-.*\\.test\\.ts.*' dist", | ||
"test:update": "npm test:all -- --updateSnapshot" | ||
}, | ||
"dependencies": { | ||
"@types/babel-plugin-tester": "^9.0.0", | ||
"debug": "^4.3.4", | ||
"lodash.mergewith": "^4.6.2", | ||
"prettier": "^2.0.1", | ||
"prettier": "^2.8.3", | ||
"strip-indent": "^3.0.0" | ||
}, | ||
"devDependencies": { | ||
"@babel/core": "^7.11.6", | ||
"@babel/plugin-proposal-async-generator-functions": "^7.10.5", | ||
"@babel/plugin-syntax-jsx": "^7.10.4", | ||
"@babel/plugin-syntax-typescript": "^7.10.4", | ||
"@babel/plugin-transform-async-to-generator": "^7.10.4", | ||
"@babel/preset-env": "^7.11.5", | ||
"kcd-scripts": "^6.5.1" | ||
"@babel/cli": "^7.20.7", | ||
"@babel/core": "^7.20.12", | ||
"@babel/eslint-parser": "^7.19.1", | ||
"@babel/helper-plugin-utils": "^7.20.2", | ||
"@babel/plugin-proposal-export-default-from": "^7.18.10", | ||
"@babel/plugin-syntax-jsx": "^7.18.6", | ||
"@babel/preset-env": "^7.20.2", | ||
"@babel/preset-typescript": "^7.18.6", | ||
"@commitlint/cli": "^17.4.2", | ||
"@commitlint/config-conventional": "^17.4.2", | ||
"@semantic-release/changelog": "^6.0.2", | ||
"@semantic-release/exec": "^6.0.3", | ||
"@semantic-release/git": "^10.0.1", | ||
"@types/babel__helper-plugin-utils": "^7.10.0", | ||
"@types/jest": "^29.2.5", | ||
"@types/lodash.mergewith": "^4.6.7", | ||
"@types/node": "^18.11.18", | ||
"@typescript-eslint/eslint-plugin": "^5.48.1", | ||
"@typescript-eslint/parser": "^5.48.1", | ||
"@xunnamius/conventional-changelog-projector": "^1.2.1", | ||
"@xunnamius/jest-types": "^1.1.3", | ||
"@xunnamius/types": "^1.3.0", | ||
"all-contributors-cli": "^6.24.0", | ||
"babel-jest": "^29.3.1", | ||
"babel-loader": "^9.1.2", | ||
"babel-plugin-explicit-exports-references": "^1.0.2", | ||
"conventional-changelog-cli": "https://xunn.at/conventional-changelog-cli", | ||
"doctoc": "^2.2.1", | ||
"dotenv": "^16.0.3", | ||
"eslint": "^8.32.0", | ||
"eslint-import-resolver-typescript": "^3.5.3", | ||
"eslint-plugin-import": "^2.27.4", | ||
"eslint-plugin-jest": "^27.2.1", | ||
"eslint-plugin-unicorn": "^45.0.2", | ||
"execa": "^5.1.1", | ||
"glob-gitignore": "^1.0.14", | ||
"husky": "^8.0.3", | ||
"jest": "^29.3.1", | ||
"jest-circus": "^29.3.1", | ||
"jest-extended": "^3.2.3", | ||
"lint-staged": "^13.1.0", | ||
"remark-capitalize-headings": "^1.0.2", | ||
"remark-cli": "^11.0.0", | ||
"remark-comment-config": "^7.0.1", | ||
"remark-frontmatter": "^4.0.1", | ||
"remark-gfm": "^3.0.1", | ||
"remark-ignore": "^1.0.5", | ||
"remark-lint": "^9.1.1", | ||
"remark-lint-definition-case": "^3.1.1", | ||
"remark-lint-fenced-code-flag": "^3.1.1", | ||
"remark-lint-fenced-code-flag-case": "^1.0.3", | ||
"remark-lint-file-extension": "^2.1.1", | ||
"remark-lint-first-heading-level": "^3.1.1", | ||
"remark-lint-heading-increment": "^3.1.1", | ||
"remark-lint-heading-whitespace": "^1.0.0", | ||
"remark-lint-heading-word-length": "^1.0.2", | ||
"remark-lint-list-item-style": "^1.1.2", | ||
"remark-lint-no-duplicate-defined-urls": "^2.1.1", | ||
"remark-lint-no-duplicate-headings-in-section": "^3.1.1", | ||
"remark-lint-no-empty-sections": "^4.0.0", | ||
"remark-lint-no-empty-url": "https://xunn.at/remark-lint-no-empty-url", | ||
"remark-lint-no-heading-like-paragraph": "^3.1.1", | ||
"remark-lint-no-heading-punctuation": "^3.1.1", | ||
"remark-lint-no-inline-padding": "^4.1.1", | ||
"remark-lint-no-literal-urls": "^3.1.1", | ||
"remark-lint-no-multiple-toplevel-headings": "^3.1.1", | ||
"remark-lint-no-reference-like-url": "^3.1.1", | ||
"remark-lint-no-shell-dollars": "^3.1.1", | ||
"remark-lint-no-shortcut-reference-image": "^3.1.1", | ||
"remark-lint-no-shortcut-reference-link": "^3.1.1", | ||
"remark-lint-no-tabs": "^3.1.1", | ||
"remark-lint-no-undefined-references": "^4.2.0", | ||
"remark-lint-ordered-list-marker-value": "^3.1.1", | ||
"remark-lint-strikethrough-marker": "^2.1.1", | ||
"remark-lint-unordered-list-marker-style": "^3.1.1", | ||
"remark-reference-links": "^6.0.1", | ||
"remark-remove-unused-definitions": "^1.0.3", | ||
"remark-remove-url-trailing-slash": "^1.0.1", | ||
"remark-renumber-references": "^1.0.4", | ||
"remark-sort-definitions": "^1.0.4", | ||
"remark-tight-comments": "^1.0.5", | ||
"remark-validate-links": "^12.1.0", | ||
"semantic-release": "https://xunn.at/semantic-release-atam", | ||
"sort-package-json": "^2.1.0", | ||
"source-map-support": "^0.5.21", | ||
"spellchecker": "^3.7.1", | ||
"toss-expression": "^0.1.2", | ||
"tsconfig-replace-paths": "^0.0.11", | ||
"type-fest": "^3.5.2", | ||
"typescript": "^4.9.4", | ||
"unique-filename": "^3.0.0" | ||
}, | ||
"peerDependencies": { | ||
"@babel/core": "^7.11.6" | ||
"@babel/core": ">=7.11.6" | ||
}, | ||
"eslintConfig": { | ||
"extends": "./node_modules/kcd-scripts/eslint.js", | ||
"rules": { | ||
"max-lines": 0, | ||
"max-lines-per-function": 0, | ||
"prefer-object-spread": 0, | ||
"no-useless-catch": 0, | ||
"babel/camelcase": 0, | ||
"babel/valid-typeof": 0, | ||
"babel/no-unused-expressions": 0, | ||
"babel/quotes": 0, | ||
"jest/prefer-todo": 0 | ||
} | ||
"engines": { | ||
"node": "^14.20.0 || ^16.16.0 || >=18.5.0" | ||
}, | ||
"eslintIgnore": [ | ||
"node_modules", | ||
"coverage", | ||
"dist", | ||
"fixtures" | ||
], | ||
"babel": { | ||
"presets": [ | ||
[ | ||
"@babel/preset-env", | ||
{ | ||
"targets": { | ||
"node": "8" | ||
}, | ||
"exclude": [ | ||
"transform-regenerator" | ||
] | ||
} | ||
] | ||
], | ||
"plugins": [ | ||
"@babel/plugin-transform-async-to-generator", | ||
"@babel/plugin-proposal-async-generator-functions", | ||
"@babel/plugin-proposal-object-rest-spread" | ||
] | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/babel-utils/babel-plugin-tester" | ||
}, | ||
"bugs": { | ||
"url": "https://github.com/babel-utils/babel-plugin-tester/issues" | ||
}, | ||
"homepage": "https://github.com/babel-utils/babel-plugin-tester#readme" | ||
"publishConfig": { | ||
"access": "public" | ||
} | ||
} |
Sorry, the diff of this file is too big to display
Deprecated
MaintenanceThe maintainer of the package marked it as deprecated. This could indicate that a single version should not be used, or that the package is no longer maintained and any new vulnerabilities will not be fixed.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 4 instances in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
185476
17
2316
1986
91
1
1
6
2
+ Addeddebug@^4.3.4
- Removed@types/babel-plugin-tester@^9.0.0
- Removed@types/babel-plugin-tester@9.0.10(transitive)
- Removed@types/babel__core@7.20.5(transitive)
- Removed@types/babel__generator@7.6.8(transitive)
- Removed@types/babel__template@7.4.4(transitive)
- Removed@types/babel__traverse@7.20.6(transitive)
- Removed@types/prettier@2.7.3(transitive)
Updatedprettier@^2.8.3