Socket
Socket
Sign inDemoInstall

humpty

Package Overview
Dependencies
Maintainers
1
Versions
2
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

humpty - npm Package Compare versions

Comparing version 0.0.1 to 0.0.2

CHANGELOG.md

6

__mocks__/simple-git.js

@@ -13,3 +13,7 @@ let storedCommits;

const [sha, fileName] = showRequest.split(":");
callback(undefined, storedFiles[sha][fileName]);
if (storedFiles[sha] && storedFiles[sha][fileName]) {
callback(undefined, storedFiles[sha][fileName]);
} else {
callback(`Fatal error: could not show ${fileName}`);
}
};

@@ -16,0 +20,0 @@ }

34

dist/App.js

@@ -19,6 +19,10 @@ "use strict";

var _printUnmentionedChanges = require("./printUnmentionedChanges");
var _printResults = require("./printResults");
var _printUnmentionedChanges2 = _interopRequireDefault(_printUnmentionedChanges);
var _printResults2 = _interopRequireDefault(_printResults);
var _exitWithCode = require("./exitWithCode");
var _exitWithCode2 = _interopRequireDefault(_exitWithCode);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

@@ -29,3 +33,8 @@

exports.default = (() => {
var _ref = _asyncToGenerator(function* ({ oldApi, newApi, gitRepo, json }) {
var _ref = _asyncToGenerator(function* ({
oldApi,
newApi,
gitRepo,
json: wantsJson
}) {
if (!oldApi) {

@@ -45,3 +54,2 @@ console.error("Error: --oldApi flag required. See --help for more info.");

}
const {

@@ -59,13 +67,9 @@ commitMessages,

if (json) {
console.log(JSON.stringify(unmentionedChanges, null, 2));
} else {
(0, _printUnmentionedChanges2.default)({
unmentionedChanges,
unmentionedChangeCount,
oldApi,
newApi
});
}
process.exit(unmentionedChangeCount === 0 ? 0 : 1);
(0, _printResults2.default)({
unmentionedChanges,
unmentionedChangeCount,
oldApi,
newApi
}, wantsJson);
(0, _exitWithCode2.default)(unmentionedChangeCount === 0 ? 0 : 1);
});

@@ -72,0 +76,0 @@

@@ -12,4 +12,12 @@ "use strict";

var _findReactApiChanges = require("./findReactApiChanges");
var _findReactApiChanges2 = _interopRequireDefault(_findReactApiChanges);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
// @flow
function findApiChanges({ oldExports, newExports }) {

@@ -27,44 +35,8 @@ return oldExports.map(oldExport => {

});
return newExport;
} else {
exportResult.apiChanges.push(...(0, _findReactApiChanges2.default)(oldExport, newExport));
}
const { api: newApi } = newExport;
oldExport.api.props.forEach(oldProp => {
const newProp = newApi.props.find(p => p.name === oldProp.name);
if (!newProp) {
exportResult.apiChanges.push({
propName: oldProp.name,
changeType: changeTypes.PROP_REMOVED
});
return;
}
if (oldProp.type.name !== newProp.type.name) {
exportResult.apiChanges.push({
propName: oldProp.name,
changeType: changeTypes.PROP_TYPE_CHANGED,
oldType: oldProp.type.name,
newType: newProp.type.name
});
}
if (!oldProp.required && newProp.required) {
exportResult.apiChanges.push({
propName: oldProp.name,
changeType: changeTypes.PROP_MADE_REQUIRED
});
}
if (oldProp.required && !newProp.required) {
exportResult.apiChanges.push({
propName: oldProp.name,
changeType: changeTypes.PROP_MADE_OPTIONAL
});
}
});
if (exportResult.apiChanges.length) {
return exportResult;
}
return exportResult.apiChanges.length ? exportResult : null;
}).filter(exportChange => !!exportChange);
} // @flow
}

@@ -7,5 +7,3 @@ "use strict";

var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
let loadFile = (() => {
let showFile = (() => {
var _ref = _asyncToGenerator(function* (repo, apiRef, filePath) {

@@ -23,3 +21,3 @@ return new Promise(function (resolve, reject) {

return function loadFile(_x, _x2, _x3) {
return function showFile(_x, _x2, _x3) {
return _ref.apply(this, arguments);

@@ -29,13 +27,122 @@ };

let loadFile = (() => {
var _ref2 = _asyncToGenerator(function* (repo, apiRef, filePath, extensionsToTry = ["", ".js", ".jsx"]) {
for (let i = 0; i < extensionsToTry.length; i++) {
const ext = extensionsToTry[i];
try {
const contents = yield showFile(repo, apiRef, `${filePath}${ext}`);
return contents;
} catch (error) {
// trying next extension
}
}
});
return function loadFile(_x4, _x5, _x6) {
return _ref2.apply(this, arguments);
};
})();
let getPropsOfDeepestFile = (() => {
var _ref3 = _asyncToGenerator(function* ({
repo,
apiRef,
sourceFile,
currentDir = ""
}) {
const fullFilePath = _path2.default.join(currentDir, sourceFile);
const source = yield loadFile(repo, apiRef, fullFilePath);
if (!source) {
throw new Error(`Could not load file for named export ${sourceFile}`);
}
const indexAst = getAST(source);
const nextSourceFile = getDefaultExportSourceFilePath(indexAst);
if (nextSourceFile) {
return yield getPropsOfDeepestFile({
repo,
apiRef,
sourceFile: nextSourceFile,
currentDir: _path2.default.dirname(fullFilePath)
});
}
return yield detectProps(source);
});
return function getPropsOfDeepestFile(_x7) {
return _ref3.apply(this, arguments);
};
})();
let detectNamedExports = (() => {
var _ref4 = _asyncToGenerator(function* ({ repo, apiRef, source: indexSource }) {
const indexAst = getAST(indexSource);
if (!indexAst) {
throw new Error("Could not parse entry file");
}
const exportsThatNeedLookup = indexAst.filter(function ({ type }) {
return ["ExportNamedDeclaration"].includes(type);
}
// "ExportDefaultDeclaration"
).filter(function ({ source }) {
return Boolean(source);
});
const results = yield Promise.all(exportsThatNeedLookup.map((() => {
var _ref5 = _asyncToGenerator(function* (toImport) {
const publicExportName = toImport.specifiers[0].exported.name;
const sourceFile = toImport.source.value;
const foundProps = yield getPropsOfDeepestFile({
repo,
apiRef,
sourceFile
});
return generateExportDefinition({
isDefaultExport: false,
name: publicExportName,
api: { props: foundProps }
});
});
return function (_x9) {
return _ref5.apply(this, arguments);
};
})()));
return results;
});
return function detectNamedExports(_x8) {
return _ref4.apply(this, arguments);
};
})();
let detectProps = (() => {
var _ref6 = _asyncToGenerator(function* (sourceToParse) {
const defaultExportApi = reactDocs.parse(sourceToParse);
return (0, _lodash2.default)(defaultExportApi.props).mapValues(function (value, name) {
return _lodash2.default.merge({}, value, { name });
}).values().value();
});
return function detectProps(_x10) {
return _ref6.apply(this, arguments);
};
})();
let loadExport = (() => {
var _ref2 = _asyncToGenerator(function* (repo, apiRef) {
var _ref7 = _asyncToGenerator(function* (repo, apiRef) {
const source = yield loadFile(repo, apiRef, "index.js");
return {
const namedExports = yield detectNamedExports({ repo, apiRef, source });
const results = [generateExportDefinition({
isDefaultExport: true,
sourceContents: source,
api: detectProps(source)
};
api: {
props: yield detectProps(source)
}
}), ...namedExports];
return results;
});
return function loadExport(_x4, _x5) {
return _ref2.apply(this, arguments);
return function loadExport(_x11, _x12) {
return _ref7.apply(this, arguments);
};

@@ -48,2 +155,6 @@ })();

var _path = require("path");
var _path2 = _interopRequireDefault(_path);
var _simpleGit = require("simple-git");

@@ -53,2 +164,6 @@

var _babylonOptions = require("./util/babylonOptions");
var _babylonOptions2 = _interopRequireDefault(_babylonOptions);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

@@ -58,10 +173,27 @@

const babylon = require("babylon");
const reactDocs = require("react-docgen");
const detectProps = source => {
const { props } = reactDocs.parse(source);
function getDefaultExportSourceFilePath(ast) {
const defaultExportAsNamed = ast.find(node => node.type === "ExportNamedDeclaration" && node.specifiers[0].exported.name === "default");
if (defaultExportAsNamed) {
return defaultExportAsNamed.source.value;
}
}
function generateExportDefinition({
isDefaultExport,
name,
sourceContents,
api
}) {
return {
props: (0, _lodash2.default)(props).mapValues((value, name) => _lodash2.default.merge({}, value, { name })).values().value()
isDefaultExport,
sourceContents,
name,
api
};
};
}

@@ -83,4 +215,9 @@ function getGitLog(repo, oldApi, newApi) {

function getAST(source) {
const ast = babylon.parse(source, _babylonOptions2.default);
return ast ? ast.program.body : null;
}
exports.default = (() => {
var _ref3 = _asyncToGenerator(function* ({
var _ref8 = _asyncToGenerator(function* ({
oldApi,

@@ -90,16 +227,12 @@ newApi,

}) {
const repo = (0, _simpleGit2.default)(gitRepo);
const repo = (0, _simpleGit2.default)(gitRepo).silent(true);
return {
commitMessages: yield getGitLog(repo, oldApi, newApi),
oldExports: [_extends({
isDefaultExport: true
}, (yield loadExport(repo, oldApi)))],
newExports: [_extends({
isDefaultExport: true
}, (yield loadExport(repo, newApi)))]
newExports: yield loadExport(repo, newApi),
oldExports: yield loadExport(repo, oldApi)
};
});
function getExportsAndCommits(_x6) {
return _ref3.apply(this, arguments);
function getExportsAndCommits(_x13) {
return _ref8.apply(this, arguments);
}

@@ -106,0 +239,0 @@

@@ -7,4 +7,9 @@ "use strict";

exports.default = printUnmentionedChanges;
// @flow
var _changeTypes = require("./changeTypes");
var changeTypes = _interopRequireWildcard(_changeTypes);
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
function condensedGitRef(gitRef) {

@@ -16,3 +21,3 @@ const isSha = gitRef.match(/^[0-9a-f]{6,}$/);

return gitRef;
}
} // @flow

@@ -29,15 +34,29 @@ function printUnmentionedChanges({

console.log(`🚨 Found ${unmentionedChangeCount} breaking API change${unmentionedChangeCount === 1 ? "" : "s"} not mentioned in git commits (${condensedGitRef(oldApi)}..${condensedGitRef(newApi)}):`);
unmentionedChanges.forEach(changedExport => {
console.log("");
if (changedExport.isDefaultExport) {
console.log("Default export");
} else {
console.log(changedExport.name);
}
const plural = unmentionedChangeCount === 1 ? "" : "s";
const intro = `🚨 Found ${unmentionedChangeCount} breaking API change${plural} not mentioned in git commits (${condensedGitRef(oldApi)}..${condensedGitRef(newApi)}):`;
const fullChanges = unmentionedChanges.map(changedExport => {
const exportName = changedExport.isDefaultExport ? "Default export" : changedExport.name;
changedExport.apiChanges.forEach(apiChange => {
console.log(` - ${apiChange.changeType}: "${apiChange.propName}" was ${apiChange.oldType}, now ${apiChange.newType}`);
});
});
const changeList = changedExport.apiChanges.map(apiChange => {
switch (apiChange.changeType) {
case changeTypes.PROP_TYPE_CHANGED:
return ` - ${apiChange.changeType}: "${apiChange.propName}" was ${apiChange.oldType}, now ${apiChange.newType}.`;
case changeTypes.PROP_REMOVED:
return ` - ${apiChange.changeType}: "${apiChange.propName}".`;
case changeTypes.PROP_MADE_REQUIRED:
return ` - ${apiChange.changeType}: "${apiChange.propName}" was optional, now required.`;
case changeTypes.PROP_MADE_OPTIONAL:
return ` - ${apiChange.changeType}: "${apiChange.propName}" was required, now optional.`;
case !changedExport.isDefaultExport && changeTypes.EXPORT_REMOVED:
return ` - ${apiChange.changeType}: ${changedExport.name} is no longer exported from the entry file.`;
case changedExport.isDefaultExport && changeTypes.EXPORT_REMOVED:
return ` - ${apiChange.changeType}: There is no longer a default export.`;
default:
break;
}
}).join("\n");
return `${exportName}\n${changeList}`;
}).join("\n");
return `${intro}\n\n${fullChanges}`;
}
{
"name": "humpty",
"version": "0.0.1",
"version": "0.0.2",
"description": "Makes sure your changelogs mention your breaking changes",

@@ -14,7 +14,3 @@ "main": "dist/index.js",

},
"keywords": [
"semver",
"breaking",
"change"
],
"keywords": ["semver", "breaking", "change"],
"author": "Ben Gummer <bengummer@gmail.com>",

@@ -26,2 +22,3 @@ "license": "ISC",

"dependencies": {
"babylon": "^6.18.0",
"lodash": "^4.17.4",

@@ -28,0 +25,0 @@ "meow": "^3.7.0",

@@ -5,2 +5,4 @@ # Humpty 🍳

[![Build Status](https://travis-ci.org/bengummer/humpty.svg?branch=master)](https://travis-ci.org/bengummer/humpty) [![npm](https://img.shields.io/npm/v/humpty.svg)]()
## Intro

@@ -25,3 +27,3 @@

### APIs
### Supported API detection

@@ -36,3 +38,3 @@ * React components

### Changelogs
### Supported changelogs

@@ -42,2 +44,26 @@ * React components

## Installation
If you're using humpty in CI you can install it globally
```sh
$ yarn global add humpty
```
Or add it as a devDependency and call it via an npm script
```json
{
"name": "my-component",
"scripts": {
"humpty": "humpty ..."
}
}
```
```sh
$ yarn add --dev humpty
$ yarn run humpty
```
## Detailed usage

@@ -61,2 +87,2 @@

[trello-board]: https://trello.com/b/kO2SRotn/humpty
[trello-board]: https://trello.com/b/kO2SRotn/humpty

@@ -6,5 +6,11 @@ // @flow

import findUnmentionedChanges from "./findUnmentionedChanges";
import printUnmentionedChanges from "./printUnmentionedChanges";
import printResults from "./printResults";
import exitWithCode from "./exitWithCode";
export default async function App({ oldApi, newApi, gitRepo, json }) {
export default async function App({
oldApi,
newApi,
gitRepo,
json: wantsJson
}) {
if (!oldApi) {

@@ -24,3 +30,2 @@ console.error("Error: --oldApi flag required. See --help for more info.");

}
const {

@@ -41,6 +46,4 @@ commitMessages,

if (json) {
console.log(JSON.stringify(unmentionedChanges, null, 2));
} else {
printUnmentionedChanges({
printResults(
{
unmentionedChanges,

@@ -50,5 +53,6 @@ unmentionedChangeCount,

newApi
});
}
process.exit(unmentionedChangeCount === 0 ? 0 : 1);
},
wantsJson
);
exitWithCode(unmentionedChangeCount === 0 ? 0 : 1);
}
// @flow
import * as changeTypes from "./changeTypes";
import findReactApiChanges from "./findReactApiChanges";

@@ -20,45 +21,11 @@ export default function findApiChanges({ oldExports, newExports }) {

});
return newExport;
} else {
exportResult.apiChanges.push(
...findReactApiChanges(oldExport, newExport)
);
}
const { api: newApi } = newExport;
oldExport.api.props.forEach(oldProp => {
const newProp = newApi.props.find(p => p.name === oldProp.name);
if (!newProp) {
exportResult.apiChanges.push({
propName: oldProp.name,
changeType: changeTypes.PROP_REMOVED
});
return;
}
if (oldProp.type.name !== newProp.type.name) {
exportResult.apiChanges.push({
propName: oldProp.name,
changeType: changeTypes.PROP_TYPE_CHANGED,
oldType: oldProp.type.name,
newType: newProp.type.name
});
}
if (!oldProp.required && newProp.required) {
exportResult.apiChanges.push({
propName: oldProp.name,
changeType: changeTypes.PROP_MADE_REQUIRED
});
}
if (oldProp.required && !newProp.required) {
exportResult.apiChanges.push({
propName: oldProp.name,
changeType: changeTypes.PROP_MADE_OPTIONAL
});
}
});
if (exportResult.apiChanges.length) {
return exportResult;
}
return exportResult.apiChanges.length ? exportResult : null;
})
.filter(exportChange => !!exportChange);
}
// @flow
import _ from "lodash";
import path from "path";
import simpleGit from "simple-git";
const babylon = require("babylon");
const reactDocs = require("react-docgen");
import babylonOptions from "./util/babylonOptions";
async function loadFile(repo, apiRef, filePath) {
async function showFile(repo, apiRef, filePath) {
return new Promise((resolve, reject) => {

@@ -19,18 +22,123 @@ repo.show([`${apiRef}:${filePath}`], (err, results) => {

const detectProps = source => {
const { props } = reactDocs.parse(source);
async function loadFile(
repo,
apiRef,
filePath,
extensionsToTry = ["", ".js", ".jsx"]
) {
for (let i = 0; i < extensionsToTry.length; i++) {
const ext = extensionsToTry[i];
try {
const contents = await showFile(repo, apiRef, `${filePath}${ext}`);
return contents;
} catch (error) {
// trying next extension
}
}
}
function getDefaultExportSourceFilePath(ast) {
const defaultExportAsNamed = ast.find(
node =>
node.type === "ExportNamedDeclaration" &&
node.specifiers[0].exported.name === "default"
);
if (defaultExportAsNamed) {
return defaultExportAsNamed.source.value;
}
}
async function getPropsOfDeepestFile({
repo,
apiRef,
sourceFile,
currentDir = ""
}) {
const fullFilePath = path.join(currentDir, sourceFile);
const source = await loadFile(repo, apiRef, fullFilePath);
if (!source) {
throw new Error(`Could not load file for named export ${sourceFile}`);
}
const indexAst = getAST(source);
const nextSourceFile = getDefaultExportSourceFilePath(indexAst);
if (nextSourceFile) {
return await getPropsOfDeepestFile({
repo,
apiRef,
sourceFile: nextSourceFile,
currentDir: path.dirname(fullFilePath)
});
}
return await detectProps(source);
}
async function detectNamedExports({ repo, apiRef, source: indexSource }) {
const indexAst = getAST(indexSource);
if (!indexAst) {
throw new Error("Could not parse entry file");
}
const exportsThatNeedLookup = indexAst
.filter(
({ type }) => ["ExportNamedDeclaration"].includes(type)
// "ExportDefaultDeclaration"
)
.filter(({ source }) => Boolean(source));
const results = await Promise.all(
exportsThatNeedLookup.map(async toImport => {
const publicExportName = toImport.specifiers[0].exported.name;
const sourceFile = toImport.source.value;
const foundProps = await getPropsOfDeepestFile({
repo,
apiRef,
sourceFile
});
return generateExportDefinition({
isDefaultExport: false,
name: publicExportName,
api: { props: foundProps }
});
})
);
return results;
}
async function detectProps(sourceToParse) {
const defaultExportApi = reactDocs.parse(sourceToParse);
return _(defaultExportApi.props)
.mapValues((value, name) => _.merge({}, value, { name }))
.values()
.value();
}
function generateExportDefinition({
isDefaultExport,
name,
sourceContents,
api
}) {
return {
props: _(props)
.mapValues((value, name) => _.merge({}, value, { name }))
.values()
.value()
isDefaultExport,
sourceContents,
name,
api
};
};
}
async function loadExport(repo, apiRef) {
const source = await loadFile(repo, apiRef, "index.js");
return {
sourceContents: source,
api: detectProps(source)
};
const namedExports = await detectNamedExports({ repo, apiRef, source });
const results = [
generateExportDefinition({
isDefaultExport: true,
sourceContents: source,
api: {
props: await detectProps(source)
}
}),
...namedExports
];
return results;
}

@@ -56,2 +164,7 @@

function getAST(source) {
const ast = babylon.parse(source, babylonOptions);
return ast ? ast.program.body : null;
}
export default async function getExportsAndCommits({

@@ -62,18 +175,8 @@ oldApi,

}) {
const repo = simpleGit(gitRepo);
const repo = simpleGit(gitRepo).silent(true);
return {
commitMessages: await getGitLog(repo, oldApi, newApi),
oldExports: [
{
isDefaultExport: true,
...(await loadExport(repo, oldApi))
}
],
newExports: [
{
isDefaultExport: true,
...(await loadExport(repo, newApi))
}
]
newExports: await loadExport(repo, newApi),
oldExports: await loadExport(repo, oldApi)
};
}
// @flow
import * as changeTypes from "./changeTypes";
function condensedGitRef(gitRef) {

@@ -21,24 +23,37 @@ const isSha = gitRef.match(/^[0-9a-f]{6,}$/);

console.log(
`🚨 Found ${unmentionedChangeCount} breaking API change${unmentionedChangeCount ===
1
? ""
: "s"} not mentioned in git commits (${condensedGitRef(
oldApi
)}..${condensedGitRef(newApi)}):`
);
unmentionedChanges.forEach(changedExport => {
console.log("");
if (changedExport.isDefaultExport) {
console.log("Default export");
} else {
console.log(changedExport.name);
}
const plural = unmentionedChangeCount === 1 ? "" : "s";
const intro = `🚨 Found ${unmentionedChangeCount} breaking API change${plural} not mentioned in git commits (${condensedGitRef(
oldApi
)}..${condensedGitRef(newApi)}):`;
const fullChanges = unmentionedChanges
.map(changedExport => {
const exportName = changedExport.isDefaultExport
? "Default export"
: changedExport.name;
changedExport.apiChanges.forEach(apiChange => {
console.log(
` - ${apiChange.changeType}: "${apiChange.propName}" was ${apiChange.oldType}, now ${apiChange.newType}`
);
});
});
const changeList = changedExport.apiChanges
.map(apiChange => {
switch (apiChange.changeType) {
case changeTypes.PROP_TYPE_CHANGED:
return ` - ${apiChange.changeType}: "${apiChange.propName}" was ${apiChange.oldType}, now ${apiChange.newType}.`;
case changeTypes.PROP_REMOVED:
return ` - ${apiChange.changeType}: "${apiChange.propName}".`;
case changeTypes.PROP_MADE_REQUIRED:
return ` - ${apiChange.changeType}: "${apiChange.propName}" was optional, now required.`;
case changeTypes.PROP_MADE_OPTIONAL:
return ` - ${apiChange.changeType}: "${apiChange.propName}" was required, now optional.`;
case !changedExport.isDefaultExport && changeTypes.EXPORT_REMOVED:
return ` - ${apiChange.changeType}: ${changedExport.name} is no longer exported from the entry file.`;
case changedExport.isDefaultExport && changeTypes.EXPORT_REMOVED:
return ` - ${apiChange.changeType}: There is no longer a default export.`;
default:
break;
}
})
.join("\n");
return `${exportName}\n${changeList}`;
})
.join("\n");
return `${intro}\n\n${fullChanges}`;
}
import simpleGit from "simple-git";
import basicComponentOld from "./dummy_exports/basic/old";
import basicComponentNew from "./dummy_exports/basic/old";
import {
entryOld,
entryNew,
namedOld,
namedNew
} from "./inputs/getExportsAndCommits/defaultAndNamed";
import * as defaultAndNamedDeep from "./inputs/getExportsAndCommits/defaultAndNamedDeep";
import * as defaultAndNamedDeep2 from "./inputs/getExportsAndCommits/defaultAndNamedDeep2";

@@ -8,3 +16,3 @@ import getExportsAndCommits from "../src/getExportsAndCommits";

describe("getExportsAndCommits()", () => {
test("return results", () => {
test("single component in root index.js", () => {
simpleGit.__setCommits__(["commit 1", "commit 2"]);

@@ -27,2 +35,99 @@ simpleGit.__setFiles__({

});
test("default component export from index.js + named export from separate file", () => {
simpleGit.__setCommits__(["commit 1", "commit 2"]);
simpleGit.__setFiles__({
aaaaaa: {
"index.js": entryOld,
"Dog.js": namedOld
},
ffffff: {
"index.js": entryNew,
"Dog.js": namedNew
}
});
return getExportsAndCommits({
oldApi: "aaaaaa",
newApi: "ffffff"
}).then(result => {
expect(result.commitMessages).toEqual(["commit 1", "commit 2"]);
expect(result.newExports.length).toBe(2);
expect(result.newExports[0].isDefaultExport).toBe(true);
expect(result.newExports[0].name).toBe(undefined);
expect(result.newExports[0].api.props.length).toBe(2);
expect(result.newExports[1].isDefaultExport).toBe(false);
expect(result.newExports[1].name).toBe("Dog");
expect(result.newExports[1].api.props.length).toBe(1);
expect(result.oldExports.length).toBe(2);
});
});
test("default component export from index.js > intermediary file > named export from separate file", () => {
simpleGit.__setCommits__(["commit 1", "commit 2"]);
simpleGit.__setFiles__({
aaaaaa: {
"index.js": defaultAndNamedDeep.entryOld,
"middle/Middle.jsx": defaultAndNamedDeep.middleOld,
"middle/components/Dog.js": defaultAndNamedDeep.deepOld
},
ffffff: {
"index.js": defaultAndNamedDeep.entryNew,
"middle/Middle.jsx": defaultAndNamedDeep.middleNew,
"middle/components/Dog.js": defaultAndNamedDeep.deepNew
}
});
return getExportsAndCommits({
oldApi: "aaaaaa",
newApi: "ffffff"
}).then(result => {
expect(result.commitMessages).toEqual(["commit 1", "commit 2"]);
expect(result.newExports.length).toBe(2);
expect(result.newExports[0].isDefaultExport).toBe(true);
expect(result.newExports[0].name).toBe(undefined);
expect(result.newExports[0].api.props.length).toBe(2);
expect(result.newExports[1].isDefaultExport).toBe(false);
expect(result.newExports[1].name).toBe("Dog");
expect(result.newExports[1].api.props.length).toBe(1);
expect(result.oldExports.length).toBe(2);
});
});
test("default component export from index.js > intermediary file > named export from separate file (variant)", () => {
simpleGit.__setCommits__(["commit 1", "commit 2"]);
simpleGit.__setFiles__({
aaaaaa: {
"index.js": defaultAndNamedDeep2.entryOld,
"middle/Middle.jsx": defaultAndNamedDeep2.middleOld,
"middle/components/Dog.js": defaultAndNamedDeep2.deepOld
},
ffffff: {
"index.js": defaultAndNamedDeep2.entryNew,
"middle/Middle.jsx": defaultAndNamedDeep2.middleNew,
"middle/components/Dog.js": defaultAndNamedDeep2.deepNew
}
});
return getExportsAndCommits({
oldApi: "aaaaaa",
newApi: "ffffff"
}).then(result => {
expect(result.commitMessages).toEqual(["commit 1", "commit 2"]);
expect(result.newExports.length).toBe(2);
expect(result.newExports[0].isDefaultExport).toBe(true);
expect(result.newExports[0].name).toBe(undefined);
expect(result.newExports[0].api.props.length).toBe(2);
expect(result.newExports[1].isDefaultExport).toBe(false);
expect(result.newExports[1].name).toBe("Dog");
expect(result.newExports[1].api.props.length).toBe(1);
expect(result.oldExports.length).toBe(2);
});
});
});

Sorry, the diff of this file is not supported yet

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