UNPKG

@n1k1t/unit-generator

Version:

Coverage based unit tests AI generator

136 lines 5.93 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.AssistantAddStrategy = void 0; const v3_1 = require("zod/v3"); const model_1 = require("./model"); const content_1 = require("../../content"); const env_1 = __importDefault(require("../../../env")); class AssistantAddStrategy extends model_1.AssistantStrategy { get schema() { return v3_1.z.object({ imports: v3_1.z.array(v3_1.z.string().describe('Code of ONLY one import statement, for example: `import ...`')).describe('List of required entity imports for unit tests'), specs: v3_1.z.array(v3_1.z.object({ code: v3_1.z.string().describe('Code of ONLY one unit test function, for example: `it(...)`'), }).describe('Unit test')).describe('List of unit tests').min(1), }); } async run() { if (!this.source.spec.content.length) { return 'SKIPPED'; } const tested = await this.source.test(); if (tested.status === 'FAILED') { return 'SKIPPED'; } const snapshot = this.source.compileSnapshot(); const context = this.compileContext(); const generated = await this.generate({ schema: this.schema, messages: { system: content_1.ArticleContent .build({ title: 'Context', tag: 'h1', content: [ context.overview, context.project, context.history, content_1.ArticleContent.build({ title: 'All lines of code those are not covered by tests, separated by commas', content: [{ code: { language: 'txt', content: this.source.cobertura.uncovered.join(', '), }, }], }), content_1.ArticleContent.build({ title: 'Import declarations already existing in unit tests code', content: [{ code: { language: this.source.spec.lang, content: this.source.spec.imports.join('\n'), }, }], }), content_1.ArticleContent.build({ title: 'Helpers and utils already declared in unit tests code', content: [{ code: { language: this.source.spec.lang, content: this.source.spec.helpers.join('\n'), }, }], }), ], }) .render(), user: content_1.ArticleContent .build({ title: 'Task', tag: 'h1', content: [{ ol: [ 'Explore the `Context` article', 'Analyze the lines of code that need to be covered by tests', 'Analyze the existing imports in the code', 'Write unit tests only for the uncovered lines of code', 'Write imports (make shure that new imports are not existing in the code)', ], }], }) .render(), }, }); if (!generated?.specs.length) { return 'EMPTY'; } const imported = await this.injectImports(generated); if (imported === 'FAILED') { return imported; } const result = await this.injectSpecs(generated); if (result !== 'DONE') { await this.source.restore(snapshot); } return result; } async injectImports(generated) { this.source.save(); const imports = generated.imports.filter((row) => row.includes('import') || row.includes('require')); if (!imports.length) { return 'EMPTY'; } await this.source.spec.prepend(imports.join('\n')).write(); const tested = await this.source.test(); if (tested.status === 'FAILED') { await this.source.restore(); return 'FAILED'; } return 'DONE'; } async injectSpecs(generated, results = []) { if (!generated.specs.length) { return 'EMPTY'; } this.source.save(); const code = generated.specs[results.length].code.trim(); await this.source.spec.append(`\n${env_1.default.marker}\n${code}`).write(); const tested = await this.source.test(); if (tested.status === 'FAILED') { this.history.add({ generated: code, message: tested.message }); await this.source.restore(); } return results.length === generated.specs.length - 1 ? results.concat([tested]).some((result) => result.status === 'PASSED') ? 'DONE' : 'FAILED' : this.injectSpecs(generated, results.concat([tested])); } static build(source, provided) { return new AssistantAddStrategy('ADD', source, provided); } } exports.AssistantAddStrategy = AssistantAddStrategy; //# sourceMappingURL=add.js.map