Files
openapi-clean-arch-gen/src/generators/report.generator.ts
didavila 463626da0c feat: add .spec.ts generation for models, mappers, repositories and use-cases
Add 4 new Mustache templates for generating unit test specs:
- model-entity.spec.mustache: tests instantiation, property setting, mock builder
- mapper.spec.mustache: tests per-property DTO→Entity mapping, instanceof, all fields
- api.repository.impl.spec.mustache: tests HTTP method, response mapping, error propagation
- api.use-cases.impl.spec.mustache: tests repository delegation, observable forwarding

Generator changes:
- Add uppercaseHttpMethod to TagOperation for spec HTTP assertions
- Add testValue to TagOperationParam for auto-generated test arguments
- Add resolveTestParamValue utility for primitive/complex type test literals
- Add specs counter to GeneratedCount and GenerationReport
- Wire 4 new renderTemplate calls in schema and tag loops
- Update report generator to count .spec.ts files

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-26 10:52:58 +01:00

63 lines
2.4 KiB
TypeScript

import fs from 'fs-extra';
import path from 'path';
import { logStep, logSuccess } from '../utils/logger';
import type { SwaggerAnalysis, GenerationReport } from '../types';
/** Counts files ending with `.mock.ts` in a directory (returns 0 if directory does not exist). */
function countMockFiles(dir: string): number {
try {
return fs.readdirSync(dir).filter((f) => f.endsWith('.mock.ts')).length;
} catch {
return 0;
}
}
/** Counts files ending with `.spec.ts` in a directory (returns 0 if directory does not exist). */
function countSpecFiles(dir: string): number {
try {
return fs.readdirSync(dir).filter((f) => f.endsWith('.spec.ts')).length;
} catch {
return 0;
}
}
/** Generates and persists the `generation-report.json` file with process statistics. */
export function generateReport(outputDir: string, analysis: SwaggerAnalysis): GenerationReport {
logStep('Generating report...');
const report: GenerationReport = {
timestamp: new Date().toISOString(),
tags: analysis.tags.length,
endpoints: Object.keys(analysis.paths).length,
outputDirectory: outputDir,
structure: {
dtos: fs.readdirSync(path.join(outputDir, 'data/dtos')).length,
repositories: fs.readdirSync(path.join(outputDir, 'data/repositories')).length,
mappers: fs.readdirSync(path.join(outputDir, 'data/mappers')).length,
useCases: fs.readdirSync(path.join(outputDir, 'domain/use-cases')).length,
providers:
fs.readdirSync(path.join(outputDir, 'di/repositories')).length +
fs.readdirSync(path.join(outputDir, 'di/use-cases')).length,
mocks:
countMockFiles(path.join(outputDir, 'data/dtos')) +
countMockFiles(path.join(outputDir, 'data/repositories')) +
countMockFiles(path.join(outputDir, 'di/repositories')) +
countMockFiles(path.join(outputDir, 'di/use-cases')) +
countMockFiles(path.join(outputDir, 'domain/use-cases')) +
countMockFiles(path.join(outputDir, 'entities/models')),
specs:
countSpecFiles(path.join(outputDir, 'entities/models')) +
countSpecFiles(path.join(outputDir, 'data/mappers')) +
countSpecFiles(path.join(outputDir, 'data/repositories')) +
countSpecFiles(path.join(outputDir, 'domain/use-cases'))
}
};
const reportPath = path.join(process.cwd(), 'generation-report.json');
fs.writeJsonSync(reportPath, report, { spaces: 2 });
logSuccess(`Report saved to: ${reportPath}`);
return report;
}