@n1k1t/unit-generator
Version:
Coverage based unit tests AI generator
149 lines • 6.09 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Spec = void 0;
const lodash_1 = __importDefault(require("lodash"));
const typescript = __importStar(require("recast/parsers/typescript"));
const prettier = __importStar(require("prettier"));
const babel = __importStar(require("recast/parsers/babel-ts"));
const recast = __importStar(require("recast"));
const utils_1 = require("../utils");
const file_1 = require("./file");
const env_1 = __importDefault(require("../env"));
class Spec extends file_1.File {
constructor() {
super(...arguments);
this.imports = [];
this.helpers = [];
this.tests = [];
}
/** Runs `prettier` over the spec file */
async pretty() {
const options = await prettier.resolveConfig(this.path, { editorconfig: true }).catch(() => null);
const formatted = await prettier
.format(this.content, { printWidth: 120, filepath: this.path, ...(options ?? {}) })
.catch(() => null);
if (formatted) {
await this.write(formatted);
}
}
parse() {
const nodes = this.extractAstNodes();
const { imports, helpers } = nodes.reduce((acc, node) => {
if (node.type === 'ExpressionStatement') {
return acc;
}
if (node.type === 'ImportDeclaration') {
acc.imports.push(recast.print(node).code);
return acc;
}
if (node.type === 'FunctionDeclaration' || node.type === 'ClassDeclaration') {
acc.helpers.push(recast.print(node).code);
return acc;
}
if (node.type === 'VariableDeclaration') {
const declarator = node.declarations.find((nested) => nested.type === 'VariableDeclarator');
declarator?.init?.type === 'CallExpression' && lodash_1.default.get(declarator.init.callee, 'name') === 'require'
? acc.imports.push(recast.print(node).code)
: acc.helpers.push(recast.print(node).code);
}
return acc;
}, {
imports: (0, utils_1.cast)([]),
helpers: (0, utils_1.cast)([]),
});
this.tests = this.extractTests(nodes);
this.imports = imports;
this.helpers = helpers;
return this;
}
async write(content) {
await super.write(content);
this.parse();
}
async refresh() {
await super.refresh();
this.parse();
}
extractAstNodes() {
try {
const ast = recast.parse(this.content, { parser: ['js', 'ts'].includes(this.lang) ? typescript : babel });
return ast.program.body;
}
catch (error) {
return [];
}
}
extractTests(nodes, prefix = '') {
return nodes
.filter((node) => node.type === 'ExpressionStatement' && node.expression.type === 'CallExpression')
.reduce((acc, node) => {
const { expression } = node;
const name = lodash_1.default.get(expression, 'callee.name');
if (name === 'it' || name === 'test') {
const title = lodash_1.default.get(expression, 'arguments')[0];
const value = lodash_1.default.get(title, 'value', '');
const start = 'start' in node ? node.start : null;
const end = 'end' in node ? node.end : null;
const content = (typeof start === 'number' && typeof end === 'number')
? this.content.substring(start, end)
: recast.print(node).code;
acc.push({
title: prefix ? `${prefix} ${value}` : value,
content: content.replace(`${env_1.default.marker}\n`, ''),
});
}
if (name === 'describe') {
const [title, content] = lodash_1.default.get(expression, 'arguments');
const value = lodash_1.default.get(title, 'value', '');
const body = lodash_1.default.get(content, 'body.body');
if (Array.isArray(body)) {
acc.push(...this.extractTests(body, prefix ? `${prefix} ${value}` : value));
}
}
return acc;
}, []);
}
static async build(location) {
const file = await file_1.File.build(location);
const cobertura = new Spec(file);
return cobertura.parse();
}
}
exports.Spec = Spec;
//# sourceMappingURL=spec.js.map