UNPKG

@n1k1t/unit-generator

Version:

Coverage based unit tests AI generator

149 lines 6.09 kB
"use strict"; 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