test(uploads): extraire extractMetadata() + tests unitaires
Refactoring minimal : le bloc de parsing de métadonnées (titre, version, description) est extrait en méthode privée extractMetadata() dans UploadsController. Le comportement de validate() est identique. 12 tests unitaires couvrent tous les cas : version standard (1.2.3, 1.0, 2, 0.0.0), extraction nom/description, et cas limites (version non-numérique, absente, vide, info absent). Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering>
This commit is contained in:
93
back/src/modules/uploads/uploads.controller.spec.ts
Normal file
93
back/src/modules/uploads/uploads.controller.spec.ts
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
import { describe, it, expect } from 'vitest';
|
||||||
|
import { UploadsController } from './uploads.controller';
|
||||||
|
|
||||||
|
/** Accès à la méthode privée sans instancier le contrôleur complet */
|
||||||
|
function extract(yamlContent: string) {
|
||||||
|
return (UploadsController.prototype as any).extractMetadata.call({}, yamlContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('UploadsController.extractMetadata()', () => {
|
||||||
|
describe('version OpenAPI standard', () => {
|
||||||
|
it('"1.2.3" → major=1, minor=2, patch=3', () => {
|
||||||
|
const result = extract('info:\n title: Test\n version: "1.2.3"');
|
||||||
|
expect(result.versionMajor).toBe(1);
|
||||||
|
expect(result.versionMinor).toBe(2);
|
||||||
|
expect(result.versionPatch).toBe(3);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('"1.0" → major=1, minor=0, patch=null', () => {
|
||||||
|
const result = extract('info:\n title: Test\n version: "1.0"');
|
||||||
|
expect(result.versionMajor).toBe(1);
|
||||||
|
expect(result.versionMinor).toBe(0);
|
||||||
|
expect(result.versionPatch).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('"2" → major=2, minor=null, patch=null', () => {
|
||||||
|
const result = extract('info:\n title: Test\n version: "2"');
|
||||||
|
expect(result.versionMajor).toBe(2);
|
||||||
|
expect(result.versionMinor).toBeNull();
|
||||||
|
expect(result.versionPatch).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('"0.0.0" → major=0, minor=0, patch=0', () => {
|
||||||
|
const result = extract('info:\n title: Test\n version: "0.0.0"');
|
||||||
|
expect(result.versionMajor).toBe(0);
|
||||||
|
expect(result.versionMinor).toBe(0);
|
||||||
|
expect(result.versionPatch).toBe(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('extraction du nom et description', () => {
|
||||||
|
it('title présent → name extrait', () => {
|
||||||
|
const result = extract('info:\n title: Mon API\n version: "1.0.0"');
|
||||||
|
expect(result.name).toBe('Mon API');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('title absent → name=null', () => {
|
||||||
|
const result = extract('info:\n version: "1.0.0"');
|
||||||
|
expect(result.name).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('description présente → description extraite', () => {
|
||||||
|
const result = extract('info:\n title: Test\n version: "1.0.0"\n description: Une description');
|
||||||
|
expect(result.description).toBe('Une description');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('description absente → description=null', () => {
|
||||||
|
const result = extract('info:\n title: Test\n version: "1.0.0"');
|
||||||
|
expect(result.description).toBeNull();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('cas limite de version', () => {
|
||||||
|
it('version non numérique ("alpha") → major=null, minor=null, patch=null', () => {
|
||||||
|
const result = extract('info:\n title: Test\n version: alpha');
|
||||||
|
expect(result.versionMajor).toBeNull();
|
||||||
|
expect(result.versionMinor).toBeNull();
|
||||||
|
expect(result.versionPatch).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('version absente → tout null', () => {
|
||||||
|
const result = extract('info:\n title: Test');
|
||||||
|
expect(result.versionMajor).toBeNull();
|
||||||
|
expect(result.versionMinor).toBeNull();
|
||||||
|
expect(result.versionPatch).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('version vide string "" → tout null', () => {
|
||||||
|
const result = extract('info:\n title: Test\n version: ""');
|
||||||
|
expect(result.versionMajor).toBeNull();
|
||||||
|
expect(result.versionMinor).toBeNull();
|
||||||
|
expect(result.versionPatch).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('info absent → tout null', () => {
|
||||||
|
const result = extract('asyncapi: "3.0.0"');
|
||||||
|
expect(result.name).toBeNull();
|
||||||
|
expect(result.description).toBeNull();
|
||||||
|
expect(result.versionMajor).toBeNull();
|
||||||
|
expect(result.versionMinor).toBeNull();
|
||||||
|
expect(result.versionPatch).toBeNull();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -156,22 +156,7 @@ export class UploadsController {
|
|||||||
|
|
||||||
/* Extraction des métadonnées depuis le fichier principal */
|
/* Extraction des métadonnées depuis le fichier principal */
|
||||||
const mainContent = fileContents.find((f) => f.name === mainFileName)!.content;
|
const mainContent = fileContents.find((f) => f.name === mainFileName)!.content;
|
||||||
const parsed = yaml.load(mainContent) as Record<string, unknown>;
|
const { name, description, versionMajor, versionMinor, versionPatch } = this.extractMetadata(mainContent);
|
||||||
const info = parsed['info'] as Record<string, unknown> | undefined;
|
|
||||||
const name = typeof info?.['title'] === 'string' ? info['title'] : null;
|
|
||||||
const description = typeof info?.['description'] === 'string' ? info['description'] : null;
|
|
||||||
|
|
||||||
/* Décomposer la version en major.minor.patch */
|
|
||||||
let versionMajor: number | null = null;
|
|
||||||
let versionMinor: number | null = null;
|
|
||||||
let versionPatch: number | null = null;
|
|
||||||
const versionStr = typeof info?.['version'] === 'string' ? info['version'] : null;
|
|
||||||
if (versionStr) {
|
|
||||||
const parts = versionStr.split('.').map((p) => parseInt(p, 10));
|
|
||||||
if (parts.length >= 1 && !isNaN(parts[0])) versionMajor = parts[0];
|
|
||||||
if (parts.length >= 2 && !isNaN(parts[1])) versionMinor = parts[1];
|
|
||||||
if (parts.length >= 3 && !isNaN(parts[2])) versionPatch = parts[2];
|
|
||||||
}
|
|
||||||
|
|
||||||
return { valid: true, type: detectedType, mainFile: mainFileName, name, versionMajor, versionMinor, versionPatch, description, errors: [] };
|
return { valid: true, type: detectedType, mainFile: mainFileName, name, versionMajor, versionMinor, versionPatch, description, errors: [] };
|
||||||
}
|
}
|
||||||
@@ -274,6 +259,33 @@ export class UploadsController {
|
|||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Extrait les métadonnées (titre, description, version) depuis le contenu YAML */
|
||||||
|
private extractMetadata(yamlContent: string): {
|
||||||
|
name: string | null;
|
||||||
|
description: string | null;
|
||||||
|
versionMajor: number | null;
|
||||||
|
versionMinor: number | null;
|
||||||
|
versionPatch: number | null;
|
||||||
|
} {
|
||||||
|
const parsed = yaml.load(yamlContent) as Record<string, unknown>;
|
||||||
|
const info = parsed['info'] as Record<string, unknown> | undefined;
|
||||||
|
const name = typeof info?.['title'] === 'string' ? info['title'] : null;
|
||||||
|
const description = typeof info?.['description'] === 'string' ? info['description'] : null;
|
||||||
|
|
||||||
|
let versionMajor: number | null = null;
|
||||||
|
let versionMinor: number | null = null;
|
||||||
|
let versionPatch: number | null = null;
|
||||||
|
const versionStr = typeof info?.['version'] === 'string' ? info['version'] : null;
|
||||||
|
if (versionStr) {
|
||||||
|
const parts = versionStr.split('.').map((p) => parseInt(p, 10));
|
||||||
|
if (parts.length >= 1 && !isNaN(parts[0])) versionMajor = parts[0];
|
||||||
|
if (parts.length >= 2 && !isNaN(parts[1])) versionMinor = parts[1];
|
||||||
|
if (parts.length >= 3 && !isNaN(parts[2])) versionPatch = parts[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
return { name, description, versionMajor, versionMinor, versionPatch };
|
||||||
|
}
|
||||||
|
|
||||||
/** Valide la syntaxe YAML et lève une BadRequestException si invalide */
|
/** Valide la syntaxe YAML et lève une BadRequestException si invalide */
|
||||||
private validateYamlSyntax(content: string, filename: string): void {
|
private validateYamlSyntax(content: string, filename: string): void {
|
||||||
try {
|
try {
|
||||||
|
|||||||
Reference in New Issue
Block a user