@typestrong/ts-mockito
Version:
Mocking library for TypeScript
275 lines • 12.1 kB
JavaScript
"use strict";
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.MockableFunctionsFinder = void 0;
var parser_1 = require("@babel/parser");
var ObjectInspector_1 = require("./ObjectInspector");
var ObjectPropertyCodeRetriever_1 = require("./ObjectPropertyCodeRetriever");
var lodash_1 = require("lodash");
var methodTokenName = new Set([
"ObjectMethod",
"ClassMethod",
"ClassPrivateMethod",
"FunctionDeclaration",
"FunctionExpression"
]);
function getPropName(n) {
if ('name' in n)
return [n.name];
if ('value' in n)
return [n.value.toString()];
if (n.type === 'PrivateName')
return getPropName(n.id);
return handleExpression(n);
}
function handleAssignment(n) {
if (methodTokenName.has(n.right.type))
return __spreadArray(__spreadArray([], handleLVal(n.left), true), handleExpression(n.right), true);
return handleExpression(n.right);
}
function handleObject(n) {
var names = [];
n.properties.forEach(function (p) {
if ('key' in p)
names.push.apply(names, getPropName(p.key));
if ('body' in p)
names.push.apply(names, p.body.body.flatMap(handleStatement));
if ('value' in p)
names.push.apply(names, handleExpression(p.value));
});
return names;
}
var isSpread = function (n) { return n.type === 'SpreadElement'; };
function handleExpression(n) {
if (!n)
return [];
switch (n.type) {
case "ArrayExpression":
return n.elements.flatMap(function (e) { return e ? (isSpread(e) ? handleUnaryLike(e) : handleExpression(e)) : []; });
case "AssignmentExpression":
return handleAssignment(n);
case "BinaryExpression":
return __spreadArray(__spreadArray([], (n.left.type !== 'PrivateName' ? handleExpression(n.left) : []), true), handleExpression(n.right), true);
case "CallExpression":
return n.arguments.flatMap(function (a) {
if (a.type === 'JSXNamespacedName')
return [];
if (a.type === 'ArgumentPlaceholder')
return [];
return isSpread(a) ? handleUnaryLike(a) : handleExpression(a);
});
case "ConditionalExpression":
return __spreadArray(__spreadArray(__spreadArray([], handleExpression(n.test), true), handleExpression(n.consequent), true), handleExpression(n.alternate), true);
case "FunctionExpression":
return handleBlock(n.body);
case "Identifier":
return [n.name];
case "LogicalExpression":
return __spreadArray(__spreadArray([], handleExpression(n.left), true), handleExpression(n.right), true);
case "MemberExpression":
return n.property.type === 'PrivateName' ? handleExpression(n.property.id) : handleExpression(n.property);
case "ObjectExpression":
return handleObject(n);
case "SequenceExpression":
return n.expressions.flatMap(handleExpression);
case "ParenthesizedExpression":
return handleExpression(n.expression);
case "UnaryExpression":
case "UpdateExpression":
case "YieldExpression":
case "AwaitExpression":
return handleExpression(n.argument);
case "ArrowFunctionExpression":
return n.body.type === 'BlockStatement' ? handleBlock(n.body) : handleExpression(n.body);
case "ClassExpression":
return handleClass(n);
case "TaggedTemplateExpression":
return handleExpression(n.tag);
case "TemplateLiteral":
return n.expressions.flatMap(function (e) { return handleExpression(e); });
case "OptionalMemberExpression":
return __spreadArray([], (n.property.type !== 'Identifier' ? handleExpression(n.property) : []), true);
case "OptionalCallExpression":
return n.arguments.flatMap(function (a) {
if (a.type === 'SpreadElement')
return handleExpression(a.argument);
if (a.type === 'JSXNamespacedName')
return [];
if (a.type === 'ArgumentPlaceholder')
return [];
return handleExpression(a);
});
case "BindExpression":
return handleExpression(n.object);
case "DoExpression":
return handleBlock(n.body);
case "RecordExpression":
case "NewExpression":
case "StringLiteral":
case "NumericLiteral":
case "BooleanLiteral":
case "RegExpLiteral":
case "NullLiteral":
case "ThisExpression":
case "MetaProperty":
case "Super":
case "Import":
case "BigIntLiteral":
case "TypeCastExpression":
case "JSXElement":
case "JSXFragment":
case "PipelinePrimaryTopicReference":
case "TupleExpression":
case "DecimalLiteral":
case "ModuleExpression":
case "TSAsExpression":
case "TSTypeAssertion":
case "TSNonNullExpression":
default:
return [];
}
}
function handleBlock(n) {
if (!n)
return [];
return n.body.flatMap(handleStatement);
}
function handleStatement(n) {
var _a;
switch (n.type) {
case "BlockStatement":
return n.body.flatMap(handleStatement);
case "DoWhileStatement":
return __spreadArray(__spreadArray([], handleExpression(n.test), true), handleStatement(n.body), true);
case "ExpressionStatement":
return handleExpression(n.expression);
case "ForInStatement":
return __spreadArray(__spreadArray([], handleExpression(n.right), true), handleStatement(n.body), true);
case "ForStatement":
return __spreadArray(__spreadArray(__spreadArray([], (n.test ? handleExpression(n.test) : []), true), (n.update ? handleExpression(n.update) : []), true), handleStatement(n.body), true);
case "FunctionDeclaration":
return __spreadArray(__spreadArray([], (n.id ? [n.id.name] : []), true), handleBlock(n.body), true);
case "IfStatement":
return __spreadArray(__spreadArray(__spreadArray([], handleExpression(n.test), true), handleStatement(n.consequent), true), (n.alternate ? handleStatement(n.alternate) : []), true);
case "LabeledStatement":
return handleStatement(n.body);
case "ReturnStatement":
return __spreadArray([], (n.argument ? handleExpression(n.argument) : []), true);
case "SwitchStatement":
return __spreadArray(__spreadArray([], handleExpression(n.discriminant), true), n.cases.flatMap(function (c) { return __spreadArray(__spreadArray([], handleExpression(c.test), true), c.consequent.flatMap(handleStatement), true); }), true);
case "ThrowStatement":
return handleExpression(n.argument);
case "TryStatement":
return __spreadArray(__spreadArray(__spreadArray([], handleBlock(n.block), true), handleBlock((_a = n.handler) === null || _a === void 0 ? void 0 : _a.body), true), handleBlock(n.finalizer), true);
case "WhileStatement":
return __spreadArray(__spreadArray([], handleExpression(n.test), true), handleStatement(n.body), true);
case "WithStatement":
return __spreadArray(__spreadArray([], handleExpression(n.object), true), handleStatement(n.body), true);
case "ClassDeclaration":
return handleClass(n);
case "ForOfStatement":
return __spreadArray(__spreadArray([], handleExpression(n.right), true), handleStatement(n.body), true);
case "VariableDeclaration":
return n.declarations.flatMap(function (d) { return handleExpression(d.init); });
case "DebuggerStatement":
case "BreakStatement":
case "ContinueStatement":
case "EmptyStatement":
case "ExportAllDeclaration":
case "ExportDefaultDeclaration":
case "ExportNamedDeclaration":
case "ImportDeclaration":
case "DeclareClass":
case "DeclareFunction":
case "DeclareInterface":
case "DeclareModule":
case "DeclareModuleExports":
case "DeclareTypeAlias":
case "DeclareOpaqueType":
case "DeclareVariable":
case "DeclareExportDeclaration":
case "DeclareExportAllDeclaration":
case "InterfaceDeclaration":
case "OpaqueType":
case "TypeAlias":
case "EnumDeclaration":
case "TSDeclareFunction":
case "TSInterfaceDeclaration":
case "TSTypeAliasDeclaration":
case "TSEnumDeclaration":
case "TSModuleDeclaration":
case "TSImportEqualsDeclaration":
case "TSExportAssignment":
case "TSNamespaceExportDeclaration":
default:
return [];
}
}
function handleLVal(n) {
if ('name' in n)
return [n.name];
if ('property' in n)
return getPropName(n.property);
return [];
}
function handleUnaryLike(n) {
return handleExpression(n.argument);
}
function handleClass(n) {
return n.body.body.flatMap(function (b) {
switch (b.type) {
case "ClassMethod":
return __spreadArray(__spreadArray([], getPropName(b.key), true), handleStatement(b.body), true);
case "ClassPrivateMethod":
return __spreadArray(__spreadArray([], getPropName(b.key), true), handleStatement(b.body), true);
case "ClassProperty":
return __spreadArray(__spreadArray([], getPropName(b.key), true), handleExpression(b.value), true);
case "ClassPrivateProperty":
return __spreadArray(__spreadArray([], getPropName(b.key), true), handleExpression(b.value), true);
case "TSIndexSignature":
case "TSDeclareMethod":
return [];
}
});
}
function handleBody(n) {
return n.body.flatMap(handleStatement);
}
var MockableFunctionsFinder = (function () {
function MockableFunctionsFinder() {
this.excludedFunctionNames = new Set(["hasOwnProperty", "function"]);
}
MockableFunctionsFinder.prototype.find = function (clazz) {
var _this = this;
var codes = this.getClassCodeAsStringWithInheritance(clazz);
var asts = codes.map(function (code) { return (0, parser_1.parse)(code); });
var names = asts.flatMap(function (ast) { return handleBody(ast.program); });
return (0, lodash_1.uniq)(names)
.filter(function (functionName) { return _this.isMockable(functionName); });
};
MockableFunctionsFinder.prototype.isMockable = function (name) {
if (!name)
return false;
return !this.excludedFunctionNames.has(name);
};
MockableFunctionsFinder.prototype.getClassCodeAsStringWithInheritance = function (clazz) {
return __spreadArray(["const clazz = ".concat(this.getClassAsString(clazz))], ObjectInspector_1.ObjectInspector.getObjectPrototypes(clazz.prototype).map(ObjectPropertyCodeRetriever_1.ObjectPropertyCodeRetriever.getObject), true);
};
MockableFunctionsFinder.prototype.getClassAsString = function (clazz) {
var classCode = typeof clazz.toString !== "undefined" ? clazz.toString() : "{}";
if (classCode === '[object Object]')
return '{}';
return classCode;
};
return MockableFunctionsFinder;
}());
exports.MockableFunctionsFinder = MockableFunctionsFinder;
//# sourceMappingURL=MockableFunctionsFinder.js.map