@n1k1t/unit-generator
Version:
Coverage based unit tests AI generator
109 lines • 4.36 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.AssistantInitStrategy = 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 AssistantInitStrategy 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').min(1),
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 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,
],
})
.render(),
user: content_1.ArticleContent
.build({
title: 'Task',
tag: 'h1',
content: [{
ol: [
'Explore the `Context` article',
'Generate unit tests',
'The first unit test must always pass, for example: `it(\'should pass\', () => expect(1).toEqual(1))`',
],
}],
})
.render(),
},
});
if (!generated?.specs.length) {
return 'EMPTY';
}
const imported = await this.injectImports(generated);
if (imported !== 'DONE') {
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'))
.append(generated.specs[0].code)
.write();
const tested = await this.source.test();
await this.source.restore();
if (tested.status === 'FAILED') {
return 'FAILED';
}
await this.source.spec.prepend(imports.join('\n')).write();
return 'DONE';
}
async injectSpecs(generated, results = []) {
if (generated.specs.length <= 1) {
return 'EMPTY';
}
/** Skip the first spec that is always passing */
const index = results.length + 1;
const code = generated.specs[index].code.trim();
this.source.save();
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 index === 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 AssistantInitStrategy('INIT', source, provided);
}
}
exports.AssistantInitStrategy = AssistantInitStrategy;
//# sourceMappingURL=init.js.map