New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

babel-plugin-tester

Package Overview
Dependencies
Maintainers
1
Versions
49
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

babel-plugin-tester - npm Package Compare versions

Comparing version 7.0.4 to 8.0.0

dist/formatters/prettier.js

473

dist/index.js
"use strict";
var _assert = _interopRequireDefault(require("assert"));
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "prettierFormatter", {
enumerable: true,
get: function () {
return _prettier.default;
}
});
Object.defineProperty(exports, "unstringSnapshotSerializer", {
enumerable: true,
get: function () {
return _unstringSnapshotSerializer.default;
}
});
exports.default = void 0;
var _path = _interopRequireDefault(require("path"));
var _pluginTester = _interopRequireDefault(require("./plugin-tester"));
var _fs = _interopRequireDefault(require("fs"));
var _prettier = _interopRequireDefault(require("./formatters/prettier"));
var _os = require("os");
var _unstringSnapshotSerializer = _interopRequireDefault(require("./unstring-snapshot-serializer"));
var _lodash = _interopRequireDefault(require("lodash.mergewith"));
var _stripIndent = _interopRequireDefault(require("strip-indent"));
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; }

@@ -27,438 +34,14 @@

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;
// istanbul ignore else (it's not worth testing)
if (expect.addSnapshotSerializer) {
expect.addSnapshotSerializer(_unstringSnapshotSerializer.default);
}
module.exports = pluginTester;
const fullDefaultConfig = {
babelOptions: {
parserOpts: {},
generatorOpts: {},
babelrc: false,
configFile: false
}
};
function mergeCustomizer(objValue, srcValue) {
if (Array.isArray(objValue)) {
return objValue.concat(srcValue);
}
return undefined;
function defaultPluginTester(options) {
return (0, _pluginTester.default)(_objectSpread({
formatResult: _prettier.default
}, options));
}
function pluginTester(_ref = {}) {
let {
/* istanbul ignore next (TODO: write a test for this) */
babel = require('@babel/core'),
plugin = requiredParam('plugin'),
pluginName = getPluginName(plugin, babel),
title: describeBlockTitle = pluginName,
pluginOptions,
tests,
fixtures,
fixtureOutputName = 'output',
filename,
endOfLine = 'lf'
} = _ref,
rest = _objectWithoutProperties(_ref, ["babel", "plugin", "pluginName", "title", "pluginOptions", "tests", "fixtures", "fixtureOutputName", "filename", "endOfLine"]);
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) {
return;
}
const testerConfig = (0, _lodash.default)({}, fullDefaultConfig, rest, mergeCustomizer);
describe(describeBlockTitle, () => {
testAsArray.forEach(testConfig => {
if (!testConfig) {
return;
}
const {
skip,
only,
title,
code,
babelOptions,
output,
snapshot,
error,
setup = noop,
teardown,
formatResult = r => r
} = (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);
} else {
it(title, testerWrapper);
}
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;
}
if (typeof returnedTeardown === 'function') {
teardowns.push(returnedTeardown);
}
try {
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;
}
}
});
return _testerWrapper.apply(this, arguments);
}
function tester() {
(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;
let errored = false;
try {
result = formatResult(fixLineEndings(babel.transform(code, babelOptions).code, endOfLine, code));
} catch (err) {
if (error) {
errored = true;
result = err;
} else {
throw err;
}
}
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, output, 'Output is incorrect.');
} else {
_assert.default.equal(result.trim(), code.trim(), 'Expected output to not change, but it did');
}
}
});
});
function toTestConfig(testConfig) {
if (typeof testConfig === 'string') {
testConfig = {
code: testConfig
};
}
const {
title,
fixture,
code = getCode(filename, fixture),
fullTitle = title || `${testNumber++}. ${pluginName}`,
output = getCode(filename, testConfig.outputFixture) || undefined,
pluginOptions: testOptions = pluginOptions
} = testConfig;
return (0, _lodash.default)({
babelOptions: {
filename: getPath(filename, fixture)
}
}, testConfig, _objectSpread({
babelOptions: {
plugins: [[plugin, testOptions]]
},
title: fullTitle,
code: (0, _stripIndent.default)(code).trim()
}, output ? {
output: (0, _stripIndent.default)(output).trim()
} : {}), mergeCustomizer);
}
}
function fixLineEndings(code, endOfLine, input) {
return code.replace(/\r?\n/g, getReplacement());
function getReplacement() {
switch (endOfLine) {
case 'lf':
{
return '\n';
}
case 'crlf':
{
return '\r\n';
}
case 'auto':
{
return _os.EOL;
}
case 'preserve':
{
const match = input.match(/\r?\n/);
if (match === null) {
return _os.EOL;
}
return match[0];
}
default:
{
throw new Error("Invalid 'endOfLine' value");
}
}
}
}
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);
}
_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({}, options, {
pluginOptions: _objectSpread({}, rootFixtureOptions, {}, options.pluginOptions, {}, fixturePluginOptions)
}));
});
return;
}
const ext = `.${codePath.split('.').pop()}`;
it(blockTitle, () => {
const {
plugin,
pluginOptions,
fixtureOutputName,
babel,
endOfLine,
formatResult = r => r
} = options,
rest = _objectWithoutProperties(options, ["plugin", "pluginOptions", "fixtureOutputName", "babel", "endOfLine", "formatResult"]);
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({}, 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();
const actual = formatResult(fixLineEndings(babel.transformSync(input, _objectSpread({}, babelOptions, {
filename: codePath
})).code, endOfLine, input));
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(), output.trim(), `actual output does not match ${fixtureOutputName}${ext}`);
});
});
};
function testFixtures(_ref2) {
let {
title: describeBlockTitle,
fixtures,
filename
} = _ref2,
rest = _objectWithoutProperties(_ref2, ["title", "fixtures", "filename"]);
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
};
}
testsArray.push(_objectSpread({
title: key
}, value));
return testsArray;
}, []);
}
function getCode(filename, fixture) {
if (!fixture) {
return '';
}
return _fs.default.readFileSync(getPath(filename, fixture), 'utf8');
}
function getPath(filename, basename) {
if (!basename) {
return undefined;
}
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');
}
}
function requiredParam(name) {
throw new Error(`${name} is a required parameter.`);
}
function getPluginName(plugin, babel) {
let name;
try {
name = plugin(babel).name;
} catch (error) {
// eslint-disable-next-line no-console
console.error('Attempting to infer the name of your plugin failed. Tried to invoke the plugin which threw the error.');
throw error;
}
(0, _assert.default)(name, 'The `pluginName` must be inferable or provided.');
return name;
} // 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,
*/
var _default = defaultPluginTester;
exports.default = _default;

@@ -1,1 +0,1 @@

{"name":"babel-plugin-tester","version":"7.0.4","description":"Utilities for testing babel plugins","main":"dist/index.js","engines":{"node":">=8","npm":">=6"},"scripts":{"build":"kcd-scripts build","lint":"kcd-scripts lint","test":"kcd-scripts test","test:update":"npm test -- --updateSnapshot --coverage","validate":"kcd-scripts validate"},"files":["dist"],"husky":{"hooks":{"pre-commit":"kcd-scripts pre-commit"}},"keywords":[],"author":"Kent C. Dodds <kent@doddsfamily.us> (http://kentcdodds.com/)","license":"MIT","dependencies":{"lodash.mergewith":"^4.6.2","strip-indent":"^3.0.0"},"devDependencies":{"@babel/core":"^7.2.0","@babel/plugin-proposal-async-generator-functions":"^7.7.0","@babel/plugin-syntax-jsx":"^7.2.0","@babel/plugin-syntax-typescript":"^7.3.3","@babel/plugin-transform-async-to-generator":"^7.7.0","@babel/preset-env":"^7.7.1","kcd-scripts":"^1.11.0"},"peerDependencies":{"@babel/core":"^7.7.2"},"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}},"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.git"},"bugs":{"url":"https://github.com/babel-utils/babel-plugin-tester/issues"},"homepage":"https://github.com/babel-utils/babel-plugin-tester#readme"}
{"name":"babel-plugin-tester","version":"8.0.0","description":"Utilities for testing babel plugins","main":"dist/index.js","engines":{"node":">=8","npm":">=6"},"scripts":{"build":"kcd-scripts build","lint":"kcd-scripts lint","test":"kcd-scripts test","test:update":"npm test -- --updateSnapshot --coverage","validate":"kcd-scripts validate"},"files":["dist","pure.js"],"husky":{"hooks":{"pre-commit":"kcd-scripts pre-commit"}},"keywords":[],"author":"Kent C. Dodds <kent@doddsfamily.us> (http://kentcdodds.com/)","license":"MIT","dependencies":{"lodash.mergewith":"^4.6.2","prettier":"^1.19.1","strip-indent":"^3.0.0"},"devDependencies":{"@babel/core":"^7.2.0","@babel/plugin-proposal-async-generator-functions":"^7.7.0","@babel/plugin-syntax-jsx":"^7.2.0","@babel/plugin-syntax-typescript":"^7.3.3","@babel/plugin-transform-async-to-generator":"^7.7.0","@babel/preset-env":"^7.7.1","kcd-scripts":"^1.11.0"},"peerDependencies":{"@babel/core":"^7.7.2"},"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}},"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.git"},"bugs":{"url":"https://github.com/babel-utils/babel-plugin-tester/issues"},"homepage":"https://github.com/babel-utils/babel-plugin-tester#readme"}

@@ -34,2 +34,5 @@ # babel-plugin-tester

- [Simple Example](#simple-example)
- [Defaults](#defaults)
- [Un-string snapshot serializer](#un-string-snapshot-serializer)
- [Prettier formatter](#prettier-formatter)
- [Inspiration](#inspiration)

@@ -68,5 +71,5 @@ - [Other Solutions](#other-solutions)

plugin: yourPlugin,
tests: [
tests: {
/* your test objects */
],
},
})

@@ -84,5 +87,5 @@ ```

plugin: identifierReversePlugin,
tests: [
tests: {
/* your test objects */
],
},
})

@@ -128,5 +131,5 @@

...
tests: [
tests: {
/* your test objects */
],
},
});

@@ -307,6 +310,20 @@

This is a function and if it's specified, it allows you to format the result
however you like. The use case for this originally was for testing codemods and
formatting their result with `prettier-eslint`.
This defaults to a function which formats your code output with prettier. If you
have prettier configured, then it will use your configuration. If you don't then
it will be default configuration.
If you'd like to specify your own, then feel free to do so. Here's the API:
```javascript
function customFormatter(code, {filename}) {
// format the code
return formattedCode
}
```
Learn more about the built-in formatter below.
The use case for this originally was for testing codemods and formatting their
result with `prettier-eslint`.
## Examples

@@ -349,4 +366,9 @@

},
snapshot: false, // use jest snapshots (only works with jest)
// use jest snapshots (only works with jest)
snapshot: false,
// defaults to a function that formats with prettier
formatResult: customFormatFunction,
// tests as objects

@@ -460,2 +482,38 @@ tests: {

## Defaults
### Un-string snapshot serializer
If you're using jest and snapshots, then the snapshot output could have a bunch
of bothersome `\"` to escape quotes because when Jest serializes a string, it
will wrap everything in double quotes. This isn't a huge deal, but it makes the
snapshots harder to read. So we automatically add a snapshot serializer for you
to remove those.
If you don't like that, then do this:
```diff
- import pluginTester from 'babel-plugin-tester'
+ import pluginTester from 'babel-plugin-tester/pure'
```
### Prettier formatter
By default, a formatter is included which formats your results with
[`prettier`](https://prettier.io). It will look for a prettier configuration
relative to the file that's being tested or the current working directory. If it
can't find one, then it uses the default configuration for prettier.
This makes your snapshots easier to read. But if you'd like to not have that,
then you can either import the `pure` file (as shown above) or you can override
the `formatResult` option:
```javascript
pluginTester({
// ... other options
formatResult: r => r,
// ... more options
})
```
## Inspiration

@@ -462,0 +520,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc