diff --git a/back/src/modules/uploads/uploads.controller.spec.ts b/back/src/modules/uploads/uploads.controller.spec.ts new file mode 100644 index 0000000..eae70a8 --- /dev/null +++ b/back/src/modules/uploads/uploads.controller.spec.ts @@ -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(); + }); + }); +}); diff --git a/back/src/modules/uploads/uploads.controller.ts b/back/src/modules/uploads/uploads.controller.ts index 2a34527..23fa8ef 100644 --- a/back/src/modules/uploads/uploads.controller.ts +++ b/back/src/modules/uploads/uploads.controller.ts @@ -156,22 +156,7 @@ export class UploadsController { /* Extraction des métadonnées depuis le fichier principal */ const mainContent = fileContents.find((f) => f.name === mainFileName)!.content; - const parsed = yaml.load(mainContent) as Record; - const info = parsed['info'] as Record | 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]; - } + const { name, description, versionMajor, versionMinor, versionPatch } = this.extractMetadata(mainContent); return { valid: true, type: detectedType, mainFile: mainFileName, name, versionMajor, versionMinor, versionPatch, description, errors: [] }; } @@ -274,6 +259,33 @@ export class UploadsController { 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; + const info = parsed['info'] as Record | 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 */ private validateYamlSyntax(content: string, filename: string): void { try {